public boolean compile(Sketch sketch, String buildPath, String primaryClassName, Target target) throws RunnerException {
    this.sketch = sketch;
    this.buildPath = buildPath;
    this.primaryClassName = primaryClassName;

    // the pms object isn't used for anything but storage
    MessageStream pms = new MessageStream(this);

    String avrBasePath = Base.getAvrBasePath();

    List<File> objectFiles = new ArrayList<File>();
    List<String> includePaths = new ArrayList<String>();

    try {
      Vector<Library> libraries = new Vector<Library>();

      LibraryManager libraryManager;
      libraryManager = new LibraryManager();
      libraryManager.buildAllUnbuilt();

      String prefLibs = Preferences.get("boards." + Preferences.get("board") + ".build.libraries");
      if (prefLibs != null) {
        String[] boardLibraries = prefLibs.trim().split("\\s+");
        for (String item : boardLibraries) {
          libraryManager.addLibrary(libraries, libraryManager.get(item));
        }
      }

      // 1. compile the target (core), outputting .o files to <buildPath> and
      // then collecting them into the core.a library file.
      includePaths.add(target.getPath());

      for (Library library : libraries) {
        includePaths.add(library.getFolder().getAbsolutePath());
      }

      List<File> targetObjectFiles =
      compileFiles(avrBasePath, buildPath, includePaths,
                   findFilesInPath(target.getPath(), "c", true),
                   findFilesInPath(target.getPath(), "cpp", true));


      // 2. compile the libraries, outputting .o files to: <buildPath>/<library>/

      for (File file : sketch.getImportedLibraries()) {
        String item = file.getName();
        libraryManager.addLibrary(libraries, libraryManager.get(item));
      }

      includePaths = new ArrayList<String>();
      includePaths.add(target.getPath());

      for (Library library : libraries) {
        String path = library.getFolder().getAbsolutePath();
        includePaths.add(library.getFolder().getAbsolutePath());
        for (File f : library.getObjectFiles()) {
          objectFiles.add(f);
        }
      }

      for (File f : targetObjectFiles) {
        objectFiles.add(f);
      }

      // 3. compile the sketch (already in the buildPath)

      objectFiles.addAll(
                        compileFiles(avrBasePath, buildPath, includePaths,
                                     findFilesInPath(buildPath, "c", false),
                                     findFilesInPath(buildPath, "cpp", false)));

      // 4. link it all together into the .elf file

      List<String> baseCommandLinker = getCommandLinker(avrBasePath, objectFiles,
                                                        buildPath + File.separator + primaryClassName + ".elf");

      baseCommandLinker.add("-L" + buildPath);
      baseCommandLinker.add("-lm");

      execAsynchronously(baseCommandLinker);
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

    List<String> baseCommandObjcopy = Arrays.asList(avrBasePath + "avr-objcopy", "-O", "-R");
    List<String> commandObjcopy;

    // 5. extract EEPROM data (from EEMEM directive) to .eep file.
    commandObjcopy = new ArrayList<String>(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
    commandObjcopy = new ArrayList<String>(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);

    return true;
  }