gt:     commandObjcopy = new ArrayList(baseCommandObjcopy);
context: /* -*- 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 processing.app.I18n;
  import processing.app.helpers.filefilters.OnlyDirs;
  import static processing.app.I18n._;
  
  import java.io.*;
  import java.util.*;
  import java.util.zip.*;
  
  
  public class Compiler implements MessageConsumer {
    static final String BUGS_URL =
      _("http://github.com/arduino/Arduino/issues");
    static final String SUPER_BADNESS =
      I18n.format(_("Compiler error, please submit this code to {0}"), BUGS_URL);
  
    Sketch sketch;
    String buildPath;
    String primaryClassName;
    boolean verbose;
    boolean sketchIsCompiled;
  
    RunnerException exception;
  
    public Compiler() { }
  
    /**
     * 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 {
      this.sketch = sketch;
      this.buildPath = buildPath;
      this.primaryClassName = primaryClassName;
      this.verbose = verbose;
      this.sketchIsCompiled = false;
  
      // the pms object isn't used for anything but storage
      MessageStream pms = new MessageStream(this);
  
      String avrBasePath = Base.getAvrBasePath();
      Map<String, String> boardPreferences = Base.getBoardPreferences();
      String core = boardPreferences.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;
      
      if (core.indexOf(':') == -1) {
        Target t = Base.getTarget();
        File coreFolder = new File(new File(t.getFolder(), "cores"), core);
        corePath = coreFolder.getAbsolutePath();
      } else {
        Target t = Base.targetsTable.get(core.substring(0, core.indexOf(':')));
        File coreFolder = new File(t.getFolder(), "cores");
        coreFolder = new File(coreFolder, core.substring(core.indexOf(':') + 1));
        corePath = coreFolder.getAbsolutePath();
      }
  
      String variant = boardPreferences.get("build.variant");
      String variantPath = null;
      
      if (variant != null) {
        if (variant.indexOf(':') == -1) {
  	Target t = Base.getTarget();
  	File variantFolder = new File(new File(t.getFolder(), "variants"), variant);
  	variantPath = variantFolder.getAbsolutePath();
        } else {
  	Target t = Base.targetsTable.get(variant.substring(0, variant.indexOf(':')));
  	File variantFolder = new File(t.getFolder(), "variants");
  	variantFolder = new File(variantFolder, variant.substring(variant.indexOf(':') + 1));
  	variantPath = variantFolder.getAbsolutePath();
        }
      }
  
      List<File> objectFiles = new ArrayList<File>();
  
     // 0. include paths for core + all libraries
  
     sketch.setCompilingProgress(20);
     List includePaths = new ArrayList();
     includePaths.add(corePath);
     if (variantPath != null) includePaths.add(variantPath);
     for (File libFolder : sketch.getImportedLibraries()) {
       // Forward compatibility with 1.5 library format
       File propertiesFile = new File(libFolder, "library.properties");
       File srcFolder = new File(libFolder, "src");
       if (propertiesFile.isFile() && srcFolder.isDirectory())
         includePaths.add(srcFolder.getPath());
       else
         includePaths.add(libFolder.getPath());
     }
  
     // 1. compile the sketch (already in the buildPath)
  
     sketch.setCompilingProgress(30);
     objectFiles.addAll(
       compileFiles(avrBasePath, buildPath, includePaths,
                 findFilesInPath(buildPath, "S", false),
                 findFilesInPath(buildPath, "c", false),
                 findFilesInPath(buildPath, "cpp", false),
                 boardPreferences));
     sketchIsCompiled = true;
  
     // 2. compile the libraries, outputting .o files to: <buildPath>/<library>/
  
     sketch.setCompilingProgress(40);
     for (File libraryFolder : sketch.getImportedLibraries()) {
       File outputFolder = new File(buildPath, libraryFolder.getName());
       createFolder(outputFolder);
       
       // Forward compatibility with 1.5 library format
       File propertiesFile = new File(libraryFolder, "library.properties");
       File srcFolder = new File(libraryFolder, "src");
       if (propertiesFile.exists() && srcFolder.isDirectory()) {
         // Is an 1.5 library with "src" folder layout
         includePaths.add(srcFolder.getAbsolutePath());
  
         // Recursively compile "src" folder
          objectFiles.addAll(recursiveCompile(avrBasePath, srcFolder,
              outputFolder, includePaths, boardPreferences));
         
         includePaths.remove(includePaths.size() - 1);
         continue;
       }
       
       // Otherwise fallback to 1.0 library layout...
       
       File utilityFolder = new File(libraryFolder, "utility");
       // 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
     // collecting them into the core.a library file.
  
     sketch.setCompilingProgress(50);
    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
      // For atmega2560, need --relax linker option to link larger
      // programs correctly.
      String optRelax = "";
      String atmega2560 = new String ("atmega2560");
      if ( atmega2560.equals(boardPreferences.get("build.mcu")) ) {
          optRelax = new String(",--relax");
      }
     sketch.setCompilingProgress(60);
      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.
      sketch.setCompilingProgress(70);
      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);
      
      // 6. build the .hex file
      sketch.setCompilingProgress(80);
  