@Override protected IProject[] build( final int kind, @SuppressWarnings("unchecked") final Map args, final IProgressMonitor monitor) throws CoreException { // don't start two builds simultaneously synchronized (buildMutex) { if (building) { // System.out.println("already building: aborting"); return null; } else building = true; } final IProgressMonitor buildMonitor; if (monitor == null) buildMonitor = new NullProgressMonitor(); else buildMonitor = monitor; try { if (kind == CLEAN_BUILD) buildMonitor.beginTask("Cleaning Project", IProgressMonitor.UNKNOWN); else buildMonitor.beginTask("Making Project", IProgressMonitor.UNKNOWN); final IProject project; if (this.project == null) project = this.getProject(); else project = this.project; if (kind == IncrementalProjectBuilder.AUTO_BUILD) return null; String makeCmd = ""; MakeUtility makeUtility = new MakeUtility(project); switch (makeUtility.getVariant()) { case GNU_MAKE: makeCmd = OcamlPlugin.getMakeFullPath(); break; case OMAKE: makeCmd = OcamlPlugin.getOMakeFullPath(); break; } makeCmd = makeCmd.trim(); if (makeCmd.trim().equals("")) { OcamlPlugin.logError( "The " + MakeUtility.getName(makeUtility.getVariant()) + " command couldn't be found. Please configure its path in the preferences."); return null; } String path = project.getLocation().toOSString(); ArrayList<String> commandLine = new ArrayList<String>(); commandLine.add(makeCmd); switch (makeUtility.getVariant()) { case OMAKE: commandLine.add("--no--progress"); commandLine.add("-w"); break; case GNU_MAKE: commandLine.add("-C" + path); break; } for (String option : makeUtility.getOptions()) commandLine.add(option); MakefileTargets makefileTargets = new MakefileTargets(project); String[] targets = null; if (kind == CLEAN_BUILD) targets = makefileTargets.getCleanTargets(); else targets = makefileTargets.getTargets(); for (String target : targets) commandLine.add(target); String[] strCommandLine = commandLine.toArray(new String[commandLine.size()]); final StringBuilder output = new StringBuilder(); IExecEvents events = new IExecEvents() { public void processNewInput(final String input) { output.append(input); Display.getDefault() .asyncExec( new Runnable() { public void run() { OcamlCompilerOutput outputView = OcamlCompilerOutput.get(); if (outputView != null) outputView.append(input); } }); } // not used, because the error output is merged with the standard output public void processNewError(String error) {} public void processEnded(int exitValue) { if (kind == CLEAN_BUILD) cleanFinished(project); else makefileFinished(output.toString(), project); } }; // clean the output from the last compilation /* * Display.getDefault().syncExec(new Runnable() { public void run() { OcamlCompilerOutput output = * OcamlCompilerOutput.get(); if (output != null) output.clear(); } }); */ File dir = project.getLocation().toFile(); ExecHelper execHelper = null; try { // use OS-inherited environment for the make process execHelper = ExecHelper.execMerge(events, strCommandLine, System.getenv(), dir); } catch (Exception e) { OcamlPlugin.logError("ocaml plugin error", e); return null; } /* * Check at regular intervals whether the user canceled the build. When that happens, we kill the * "make" process. */ while (execHelper.isRunning()) { if (buildMonitor.isCanceled()) execHelper.kill(); try { buildMonitor.worked(1); Thread.sleep(100); } catch (InterruptedException e) { } } execHelper.join(); return null; } finally { buildMonitor.worked(1); buildMonitor.done(); building = false; } }