/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* Part of the Processing project - http://processing.org Copyright (c) 2004-08 Ben Fry and Casey Reas Copyright (c) 2001-04 Massachusetts Institute of Technology This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package processing.app.debug; import processing.app.Base; import processing.app.Preferences; import processing.app.Sketch; import processing.app.SketchCode; import processing.core.*; import java.io.*; import java.util.*; import java.util.zip.*; import java.text.MessageFormat; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.PropertyConfigurator; import org.apache.log4j.Logger; import org.apache.log4j.Level; public class Compiler implements MessageConsumer { static Logger logger = Logger.getLogger(Base.class.getName()); static final String BUGS_URL = "http://code.google.com/p/arduino/issues/list"; static final String SUPER_BADNESS = "Compiler error, please submit this code to " + BUGS_URL; Sketch sketch; String buildPath; String primaryClassName; String platform; boolean verbose; String board; //CommandRunner runner; RunnerException exception; HashMap<String, String> configPreferences; Map<String, String> boardPreferences; Map<String, String> platformPreferences; Map<String, String> sketchPreferences; String avrBasePath; String corePath; List<File> objectFiles; ArrayList<String> includePaths; public Compiler() { logger.debug("DEBUG: Compiler(): Start no arguments"); } /** * Compile with avr-gcc. * * @param sketch * Sketch object to be compiled. * @param buildPath * Where the temporary files live and will be built from. * @param primaryClassName * the name of the combined sketch file w/ extension * @return true if successful. * @throws RunnerException * Only if there's a problem. Only then. */ public boolean compile(Sketch sketch, String buildPath,String primaryClassName, boolean verbose) throws RunnerException { logger.debug("DEBUG: Compiler.java: Start Compile(...)."); this.sketch = sketch; this.buildPath = buildPath; this.primaryClassName = primaryClassName; this.verbose = verbose; // the pms object isn't used for anything but storage MessageStream pms = new MessageStream(this); boardPreferences = new HashMap(Base.getBoardPreferences()); String buildCore = boardPreferences.get("build.core"); if (buildCore == null) { RunnerException re = new RunnerException("No board selected; please choose a board from the Tools > Board menu."); re.hideStackTrace(); throw re; } //Check for null platform, and use system default if not found platform = boardPreferences.get("platform"); if (platform == null) { platformPreferences = new HashMap(Base.getPlatformPreferences()); } else { platformPreferences = new HashMap(Base.getPlatformPreferences(platform)); } //Get the preferences file from the sketch folder File sketchFolder = sketch.getFolder(); sketchPreferences = Base.getSketchPreferences(sketchFolder) ; //Put all the global preference configuration into one Master configpreferences configPreferences = mergePreferences( Preferences.getMap(), platformPreferences, boardPreferences, sketchPreferences); avrBasePath = configPreferences.get("compiler.path"); logger.debug("avrBasePath: " + avrBasePath); if (avrBasePath == null) { avrBasePath = Base.getAvrBasePath(); } else { //Put in the system path in the compiler path if available MessageFormat compileFormat = new MessageFormat(avrBasePath); String basePath = System.getProperty("user.dir"); if (Base.isMacOS()) { logger.debug("basePath: " + basePath); basePath += "/mpide.app/Contents/Resources/Java"; } Object[] Args = {basePath}; avrBasePath = compileFormat.format( Args ); } this.board = configPreferences.get("board"); if (this.board == "") { this.board = "_UNKNOWN"; } String core = configPreferences.get("build.core"); if (core == null) { RunnerException re = new RunnerException( "No board selected; please choose a board from the Tools > Board menu."); re.hideStackTrace(); throw re; } //String corePath; File systemFolder = null; if (core.indexOf(':') == -1) { Target t = Base.getTarget(); File coreFolder = new File(new File(t.getFolder(), "cores"), core); this.corePath = coreFolder.getAbsolutePath(); systemFolder = new File(t.getFolder(), "system"); } else { Target t = Base.targetsTable.get(core.substring(0, core.indexOf(':'))); File coresFolder = new File(t.getFolder(), "cores"); File coreFolder = new File(coresFolder, core.substring(core.indexOf(':') + 1)); this.corePath = coreFolder.getAbsolutePath(); systemFolder = new File(t.getFolder(), "system"); } /* * Debug corePath */ logger.debug("corePaths: " + this.corePath); String variant = boardPreferences.get("build.variant"); String variantPath = null; if (variant != null) { if (variant.indexOf(':') == -1) { Target t = Base.getTarget(); variantPath = t.getVariantFolder(variant).getAbsolutePath(); } else { Target t = Base.targetsTable.get(variant.substring(0, variant.indexOf(':'))); variantPath = t.getVariantFolder(variant).getAbsolutePath(); } } logger.debug("Variant Path: " + variantPath); this.objectFiles = new ArrayList<File>(); // 0. include paths for core + all libraries logger.debug("0. getIncludes"); sketch.setCompilingProgress(20); this.includePaths = getIncludes(this.corePath); if (variantPath != null) { includePaths.add(variantPath); } for (File file : sketch.getImportedLibraries()) { includePaths.add(file.getPath()); } // 1. compile the sketch (already in the buildPath) logger.debug("1. compileSketch"); compileSketch(avrBasePath, buildPath, includePaths, systemFolder); sketch.setCompilingProgress(30); // 2. compile the libraries, outputting .o files to: // <buildPath>/<library>/ //Doesn't really use configPreferences logger.debug("2. compileLibraries"); compileLibraries(avrBasePath, buildPath, includePaths, systemFolder); sketch.setCompilingProgress(40); // 3. compile the core, outputting .o files to <buildPath> and then // collecting them into the core.a library file. logger.debug("3. compileCore"); compileCore(avrBasePath, buildPath, corePath, variant, variantPath, systemFolder); sketch.setCompilingProgress(50); if (systemFolder != null && systemFolder.exists() && systemFolder.isDirectory()) { logger.debug("3.5. compileSystemFolder"); compileSystemFolder(avrBasePath, buildPath, systemFolder.getAbsolutePath(), variant, variantPath, systemFolder); sketch.setCompilingProgress(55); } // 4. link it all together into the .elf file logger.debug("4. compileLink"); compileLink(avrBasePath, buildPath, this.corePath, includePaths, systemFolder); sketch.setCompilingProgress(60); // 5. extract EEPROM data (from EEMEM directive) to .eep file. logger.debug("5. compileEep"); compileEep(avrBasePath, buildPath, includePaths, systemFolder); sketch.setCompilingProgress(70); // 6. build the .hex file logger.debug("6. compileHex"); sketch.setCompilingProgress(80); compileHex(avrBasePath, buildPath, includePaths, systemFolder); sketch.setCompilingProgress(90); //done logger.debug("7. compile done"); return true; } private List<File> compileFiles(String avrBasePath, String buildPath, ArrayList<String> includePaths, List<File> sSources, List<File> cSources, List<File> cppSources, File systemFolder) throws RunnerException { List<File> objectPaths = new ArrayList<File>(); for (File file : sSources) { String objectPath = buildPath + File.separator + file.getName() + ".o"; objectPaths.add(new File(objectPath)); execAsynchronously(getCommandCompilerS(avrBasePath, includePaths, file.getAbsolutePath(), objectPath, systemFolder)); } for (File file : cSources) { String objectPath = buildPath + File.separator + file.getName() + ".o"; objectPaths.add(new File(objectPath)); execAsynchronously(getCommandCompilerC(avrBasePath, includePaths, file.getAbsolutePath(), objectPath, systemFolder)); } for (File file : cppSources) { String objectPath = buildPath + File.separator + file.getName() + ".o"; objectPaths.add(new File(objectPath)); execAsynchronously(getCommandCompilerCPP(avrBasePath, includePaths, file.getAbsolutePath(), objectPath, systemFolder)); } return objectPaths; } boolean firstErrorFound; boolean secondErrorFound; /*** * Exec as String instead of Array * */ private void execAsynchronously(String command) throws RunnerException { { logger.debug("execAsynchronously: start"); String[] commandArray = command.split("::"); List<String> stringList = new ArrayList<String>(); for(String string : commandArray) { string = string.trim(); if(string != null && string.length() > 0) { stringList.add(string); } } commandArray = stringList.toArray(new String[stringList.size()]); int result = 0; if (verbose || Preferences.getBoolean("build.verbose")) { System.out.print(command.replace(":"," ")); System.out.println(); /*if(logger.isDebugEnabled()) { for (int i = 0; i < commandArray.length; i++) { logger.debug("commandArray[" + i + "]: " + commandArray[i]); } logger.debug("Command: " + command.replace(":"," ")); }*/ } firstErrorFound = false; // haven't found any errors yet secondErrorFound = false; Process process; try { process = Runtime.getRuntime().exec(commandArray); } catch (IOException e) { RunnerException re = new RunnerException(e.getMessage()); re.hideStackTrace(); throw re; } MessageSiphon in = new MessageSiphon(process.getInputStream(), this); MessageSiphon err = new MessageSiphon(process.getErrorStream(), this); // wait for the process to finish. if interrupted // before waitFor returns, continue waiting boolean running = true; while (running) { try { if (in.thread != null) in.thread.join(); if (err.thread != null) err.thread.join(); result = process.waitFor(); //System.out.println("result is " + result); running = false; } catch (InterruptedException ignored) { } } // an error was queued up by message(), barf this back to compile(), // which will barf it back to Editor. if you're having trouble // discerning the imagery, consider how cows regurgitate their food // to digest it, and the fact that they have five stomaches. // //System.out.println("throwing up " + exception); if (exception != null) { throw exception; } if (result > 1) { // a failure in the tool (e.g. unable to locate a sub-executable) System.err.println(command + " returned " + result); } if (result != 0) { RunnerException re = new RunnerException("Error running."); re.hideStackTrace(); throw re; } } } /** * Part of the MessageConsumer interface, this is called whenever a piece * (usually a line) of error message is spewed out from the compiler. The * errors are parsed for their contents and line number, which is then * reported back to Editor. */ public void message(String s) { int i; // remove the build path so people only see the filename // can't use replaceAll() because the path may have characters in it // which // have meaning in a regular expression. if (!verbose) { while ((i = s.indexOf(buildPath + File.separator)) != -1) { s = s.substring(0, i) + s.substring(i + (buildPath + File.separator).length()); } } // look for error line, which contains file name, line number, // and at least the first line of the error message String errorFormat = "([\\w\\d_]+.\\w+):(\\d+):\\s*error:\\s*(.*)\\s*"; String[] pieces = PApplet.match(s, errorFormat); // if (pieces != null && exception == null) { // exception = sketch.placeException(pieces[3], pieces[1], // PApplet.parseInt(pieces[2]) - 1); // if (exception != null) exception.hideStackTrace(); // } if (pieces != null) { RunnerException e = sketch.placeException(pieces[3], pieces[1], PApplet.parseInt(pieces[2]) - 1); // replace full file path with the name of the sketch tab (unless // we're // in verbose mode, in which case don't modify the compiler output) if (e != null && !verbose) { SketchCode code = sketch.getCode(e.getCodeIndex()); String fileName = code .isExtension(sketch.getDefaultExtension()) ? code .getPrettyName() : code.getFileName(); s = fileName + ":" + e.getCodeLine() + ": error: " + e.getMessage(); } if (pieces[3].trim().equals("SPI.h: No such file or directory")) { e = new RunnerException( "Please import the SPI library from the Sketch > Import Library menu."); s += "\nAs of Arduino 0019, the Ethernet library depends on the SPI library." + "\nYou appear to be using it or another library that depends on the SPI library."; } if (exception == null && e != null) { exception = e; exception.hideStackTrace(); } } System.err.print(s); } // /////////////////////////////////////////////////////////////////////////// //What conditions is getCommandCompilerS invoke from? private String getCommandCompilerS(String avrBasePath, ArrayList<String> includePaths, String sourceName, String objectName, File systemFolder) { logger.debug("getCommandCompilerS: start"); String baseCommandString = configPreferences.get("recipe.cpp.o.pattern"); MessageFormat compileFormat = new MessageFormat(baseCommandString); //getIncludes to String String includes = preparePaths(includePaths); Object[] Args = { avrBasePath, //0 configPreferences.get("compiler.cpp.cmd"), //1 configPreferences.get("compiler.S.flags"), //2 configPreferences.get("compiler.cpudef"), //3 configPreferences.get("build.mcu"), //4 configPreferences.get("build.f_cpu"), //5 configPreferences.get("software") + "=" + ( configPreferences.get("core.version") != null ? configPreferences.get("core.version") : Base.REVISION), configPreferences.get("board") , //7, configPreferences.get("compiler.define") + " " + configPreferences.get("board.define") , //8 includes, //9 sourceName, //10 objectName, //11 systemFolder.getAbsolutePath() // 12 }; return compileFormat.format( Args ); } //removed static private String getCommandCompilerC(String avrBasePath, ArrayList<String> includePaths, String sourceName, String objectName, File systemFolder) { logger.debug("getCommandCompilerC: start"); String baseCommandString = configPreferences.get("recipe.c.o.pattern"); MessageFormat compileFormat = new MessageFormat(baseCommandString); //getIncludes to String String includes = preparePaths(includePaths); Object[] Args = { avrBasePath, configPreferences.get("compiler.c.cmd"), configPreferences.get("compiler.c.flags"), configPreferences.get("compiler.cpudef"), configPreferences.get("build.mcu"), configPreferences.get("build.f_cpu"), configPreferences.get("software") + "=" + ( configPreferences.get("core.version") != null ? configPreferences.get("core.version") : Base.REVISION), configPreferences.get("board"), configPreferences.get("compiler.define") + " " + configPreferences.get("board.define"), includes, sourceName, objectName, systemFolder.getAbsolutePath() }; return compileFormat.format( Args ); } private String getCommandCompilerCPP(String avrBasePath, ArrayList<String> includePaths, String sourceName, String objectName, File systemFolder) { logger.debug("getCommandCompilerCPP: start"); String baseCommandString = configPreferences.get("recipe.cpp.o.pattern"); MessageFormat compileFormat = new MessageFormat(baseCommandString); //getIncludes to String String includes = preparePaths(includePaths); logger.debug("Source: " + sourceName); Object[] Args = { avrBasePath, configPreferences.get("compiler.cpp.cmd"), configPreferences.get("compiler.cpp.flags"), configPreferences.get("compiler.cpudef"), configPreferences.get("build.mcu"), configPreferences.get("build.f_cpu"), configPreferences.get("software") + "=" + ( configPreferences.get("core.version") != null ? configPreferences.get("core.version") : Base.REVISION), configPreferences.get("board"), configPreferences.get("compiler.define") + " " + configPreferences.get("board.define"), includes, sourceName, objectName, systemFolder.getAbsolutePath() }; return compileFormat.format( Args ); } // /////////////////////////////////////////////////////////////////////////// static private void createFolder(File folder) throws RunnerException { if (folder.isDirectory()) return; if (!folder.mkdir()) throw new RunnerException("Couldn't create: " + folder); } /** * Given a folder, return a list of the header files in that folder (but not * the header files in its sub-folders, as those should be included from * within the header files at the top-level). */ static public String[] headerListFromIncludePath(String path) { FilenameFilter onlyHFiles = new FilenameFilter() { public boolean accept(File dir, String name) { return name.endsWith(".h"); } }; return (new File(path)).list(onlyHFiles); } static public ArrayList<File> findFilesInPath(String path, String extension, boolean recurse) { return findFilesInFolder(new File(path), extension, recurse); } static public ArrayList<File> findFilesInFolder(File folder, String extension, boolean recurse) { ArrayList<File> files = new ArrayList<File>(); if (folder.listFiles() == null) return files; for (File file : folder.listFiles()) { if (file.getName().startsWith(".")) continue; // skip hidden files if (file.getName().endsWith("." + extension)) files.add(file); if (recurse && file.isDirectory()) { files.addAll(findFilesInFolder(file, extension, true)); } } return files; } // 0. include paths for core + all libraries ArrayList<String> getIncludes(String corePath) { logger.debug("corePath: " + corePath); logger.debug("getSketchFlderPath: " + sketch.getFolder().toString()); ArrayList<String> includePaths = new ArrayList(); //add the sketch path to the includes includePaths.add(sketch.getFolder().toString()); includePaths.add(corePath); for (File file : sketch.getImportedLibraries()) { logger.debug("getImportedLibraries: " + file.getPath()); includePaths.add(file.getPath()); } return includePaths; } // 1. compile the sketch (already in the buildPath) void compileSketch(String avrBasePath, String buildPath, ArrayList<String> includePaths, File systemFolder) throws RunnerException { logger.debug("compileSketch: start"); this.objectFiles.addAll(compileFiles(avrBasePath, buildPath, includePaths, findFilesInPath(buildPath, "S", false), findFilesInPath(buildPath, "c", false), findFilesInPath(buildPath, "cpp", false), systemFolder)); } // 2. compile the libraries, outputting .o files to: // <buildPath>/<library>/ void compileLibraries (String avrBasePath, String buildPath, ArrayList<String> includePaths, File systemFolder) throws RunnerException { logger.debug("compileLibraries: start"); 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 this.includePaths.add(utilityFolder.getAbsolutePath()); this.objectFiles.addAll(compileFiles(avrBasePath, outputFolder.getAbsolutePath(), includePaths, findFilesInFolder(libraryFolder, "S", false), findFilesInFolder(libraryFolder, "c", false), findFilesInFolder(libraryFolder, "cpp", false), systemFolder)); outputFolder = new File(outputFolder, "utility"); createFolder(outputFolder); this.objectFiles.addAll(compileFiles(avrBasePath, outputFolder.getAbsolutePath(), includePaths, findFilesInFolder(utilityFolder, "S", false), findFilesInFolder(utilityFolder, "c", false), findFilesInFolder(utilityFolder, "cpp", false), systemFolder)); // other libraries should not see this library's utility/ folder this.includePaths.remove(includePaths.size() - 1); } } // 3. compile the core, outputting .o files to <buildPath> and then // collecting them into the core.a library file. void compileCore (String avrBasePath, String buildPath, String corePath, String variant, String variantPath, File systemFolder) throws RunnerException { logger.debug("compileCore(...) start"); ArrayList<String> includePaths = new ArrayList(); includePaths.add(corePath); //include core path only if (variantPath != null) includePaths.add(variantPath); if (variantPath != null) { objectFiles.addAll(compileFiles(avrBasePath, buildPath, includePaths, findFilesInPath(variantPath, "S", false), findFilesInPath(variantPath, "c", false), findFilesInPath(variantPath, "cpp", false), systemFolder )); } String baseCommandString = configPreferences.get("recipe.ar.pattern"); String commandString = ""; MessageFormat compileFormat = new MessageFormat(baseCommandString); List<File> coreObjectFiles = compileFiles( avrBasePath, buildPath, includePaths, findFilesInPath(corePath, "S", true), findFilesInPath(corePath, "c", true), findFilesInPath(corePath, "cpp", true), systemFolder); for (File file : coreObjectFiles) { //List commandAR = new ArrayList(baseCommandAR); //commandAR = commandAR + file.getAbsolutePath(); Object[] Args = { avrBasePath, configPreferences.get("compiler.ar.cmd"), configPreferences.get("compiler.ar.flags"), //corePath, buildPath + File.separator, "core.a", //objectName file.getAbsolutePath(), systemFolder.getAbsolutePath() }; commandString = compileFormat.format( Args ); execAsynchronously(commandString); } } // 3.5. compile the system folder, outputting .o files to <buildPath> and then // collecting them into the system.a library file. void compileSystemFolder (String avrBasePath, String buildPath, String corePath, String variant, String variantPath, File systemFolder) throws RunnerException { logger.debug("compileSusyemFolder(...) start"); ArrayList<String> includePaths = new ArrayList(); includePaths.add(corePath); //include core path only if (variantPath != null) includePaths.add(variantPath); String baseCommandString = configPreferences.get("recipe.ar.pattern"); String commandString = ""; MessageFormat compileFormat = new MessageFormat(baseCommandString); List<File> coreObjectFiles = compileFiles( avrBasePath, buildPath, includePaths, findFilesInPath(corePath, "S", true), findFilesInPath(corePath, "c", true), findFilesInPath(corePath, "cpp", true), systemFolder); for (File file : coreObjectFiles) { //List commandAR = new ArrayList(baseCommandAR); //commandAR = commandAR + file.getAbsolutePath(); Object[] Args = { avrBasePath, configPreferences.get("compiler.ar.cmd"), configPreferences.get("compiler.ar.flags"), //corePath, buildPath + File.separator, "system.a", //objectName file.getAbsolutePath(), systemFolder.getAbsolutePath() }; commandString = compileFormat.format( Args ); execAsynchronously(commandString); } } // 4. link it all together into the .elf file void compileLink(String avrBasePath, String buildPath, String corePath, ArrayList<String> includePaths, File systemFolder) throws RunnerException { logger.debug("compileLink: start"); String baseCommandString = configPreferences.get("recipe.c.combine.pattern"); String commandString = ""; MessageFormat compileFormat = new MessageFormat(baseCommandString); String objectFileList = ""; for (File file : objectFiles) { objectFileList = objectFileList + file.getAbsolutePath() + "::"; } String variant = configPreferences.get("build.variant"); Target t; String variantPath; if (variant.indexOf(':') == -1) { t = Base.getTarget(); variantPath = t.getVariantFolder(variant).getAbsolutePath(); } else { t = Base.targetsTable.get(variant.substring(0, variant.indexOf(':'))); variantPath = t.getVariantFolder(variant.substring(0, variant.indexOf(':'))).getAbsolutePath(); } String ldscript = configPreferences.get("ldscript"); String foundPath = null; if (ldscript != null) { File testFile = null; testFile = new File(variantPath, ldscript); logger.debug("Searching for " + variantPath + "/" + ldscript + "..."); if (testFile.exists()) { logger.debug("... found"); foundPath = variantPath; } else { logger.debug("Searching for " + corePath + "/" + ldscript + "..."); testFile = new File(corePath, ldscript); if (testFile.exists()) { logger.debug("... found"); foundPath = corePath; } } if (foundPath == null) { System.out.println("Linker script not found: " + ldscript); return; } } else { ldscript = ""; foundPath = ""; } File systemArchive = new File(buildPath, "system.a"); if (systemArchive.exists()) { Object[] Args = { avrBasePath, configPreferences.get("compiler.c.elf.cmd"), configPreferences.get("compiler.c.elf.flags"), configPreferences.get("compiler.cpudef"), configPreferences.get("build.mcu"), buildPath + File.separator, primaryClassName, objectFileList, buildPath + File.separator + "core.a", systemArchive.getAbsolutePath(), buildPath, foundPath, configPreferences.get("ldscript") != null ? configPreferences.get("ldscript") : "", corePath, configPreferences.get("ldcommon") != null ? configPreferences.get("ldcommon") : "", systemFolder.getAbsolutePath() }; commandString = compileFormat.format( Args ); logger.debug("Link command: " + commandString); execAsynchronously(commandString); } else { Object[] Args = { avrBasePath, configPreferences.get("compiler.c.elf.cmd"), configPreferences.get("compiler.c.elf.flags"), configPreferences.get("compiler.cpudef"), configPreferences.get("build.mcu"), buildPath + File.separator, primaryClassName, objectFileList, buildPath + File.separator + "core.a", "", buildPath, foundPath, configPreferences.get("ldscript") != null ? configPreferences.get("ldscript") : "", corePath, configPreferences.get("ldcommon") != null ? configPreferences.get("ldcommon") : "", systemFolder.getAbsolutePath() }; commandString = compileFormat.format( Args ); logger.debug("Link command: " + commandString); execAsynchronously(commandString); } } // 5. extract EEPROM data (from EEMEM directive) to .eep file. void compileEep (String avrBasePath, String buildPath, ArrayList<String> includePaths, File systemFolder) throws RunnerException { logger.debug("compileEep: start"); String baseCommandString = configPreferences.get("recipe.objcopy.eep.pattern"); String commandString = ""; MessageFormat compileFormat = new MessageFormat(baseCommandString); String objectFileList = ""; Object[] Args = { avrBasePath, configPreferences.get("compiler.objcopy.cmd"), configPreferences.get("compiler.objcopy.eep.flags"), buildPath + File.separator + primaryClassName, buildPath + File.separator + primaryClassName, systemFolder.getAbsolutePath() }; commandString = compileFormat.format( Args ); execAsynchronously(commandString); } // 6. build the .hex file void compileHex (String avrBasePath, String buildPath, ArrayList<String> includePaths, File systemFolder) throws RunnerException { logger.debug("compileHex: start"); String baseCommandString = configPreferences.get("recipe.objcopy.hex.pattern"); String commandString = ""; MessageFormat compileFormat = new MessageFormat(baseCommandString); String objectFileList = ""; Object[] Args = { avrBasePath, configPreferences.get("compiler.elf2hex.cmd"), configPreferences.get("compiler.elf2hex.flags"), buildPath + File.separator + primaryClassName, buildPath + File.separator + primaryClassName, systemFolder.getAbsolutePath() }; commandString = compileFormat.format( Args ); execAsynchronously(commandString); } //merge all the preferences file in the correct order of precedence HashMap mergePreferences(Map Preferences, Map platformPreferences, Map boardPreferences, Map sketchPreferences) { HashMap _map = new HashMap(); Iterator iterator = Preferences.entrySet().iterator(); while(iterator.hasNext()) { Map.Entry pair = (Map.Entry)iterator.next(); if (pair.getValue() == null) { _map.put(pair.getKey(), ""); } else { _map.put(pair.getKey(), pair.getValue()); } } //logger.debug("Preferences Platform Dump: " + platformPreferences); iterator = platformPreferences.entrySet().iterator(); while(iterator.hasNext()) { Map.Entry pair = (Map.Entry)iterator.next(); if (pair.getValue() == null) { _map.put(pair.getKey(), ""); } else { _map.put(pair.getKey(), pair.getValue()); } //System.out.println(pair.getKey() + " = " + pair.getValue()); } //System.out.println("Done: platformPreferences"); iterator = boardPreferences.entrySet().iterator(); while(iterator.hasNext()) { Map.Entry pair = (Map.Entry)iterator.next(); if (pair.getValue() == null) { _map.put(pair.getKey(), ""); } else { _map.put(pair.getKey(), pair.getValue()); } //System.out.println(pair.getKey() + " = " + pair.getValue()); } //System.out.println("Done: boardPreferences"); iterator = sketchPreferences.entrySet().iterator(); while(iterator.hasNext()) { Map.Entry pair = (Map.Entry)iterator.next(); if (pair.getValue() == null) { _map.put(pair.getKey(), ""); } else { _map.put(pair.getKey(), pair.getValue()); } //System.out.println(pair.getKey() + " = " + pair.getValue()); } //System.out.println("Done: boardPreferences"); // logger.debug("Final Preferences Dump: " + _map); return _map; } private static String preparePaths(ArrayList<String> includePaths) { //getIncludes to String //logger.debug("Start: Prepare paths"); String includes = ""; for (int i = 0; i < includePaths.size(); i++) { includes = includes + (" -I" + (String) includePaths.get(i)) + "::"; } //logger.debug("Paths prepared: " + includes); return includes; } }