diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/BuildProcessManager.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/BuildProcessManager.java new file mode 100644 index 00000000000..d75a5539e52 --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/BuildProcessManager.java @@ -0,0 +1,183 @@ +/******************************************************************************* + * Copyright (c) 2006 Intel Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Intel Corporation - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.managedbuilder.internal.buildmodel; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.eclipse.cdt.managedbuilder.buildmodel.IBuildCommand; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; + +/** + * This class implements process pool management for internal builder + * + * NOTE: This class is subject to change and discuss, + * and is currently available in experimental mode only + */ +public class BuildProcessManager { + protected OutputStream out; + protected OutputStream err; + protected boolean show; + protected ProcessLauncher[] processes; + protected int maxProcesses; + +// Number of CPUs is not dependent of object instance. +// But user can change UI settings for processes number. +// So we cannot set procNumber directly to maxProcesses. + static int procNumber = 0; + + /** + * Initializes process manager + * + * @param _out Output stream + * @param _err Error output stream + * @param _show If true, print command line before launching + */ + public BuildProcessManager(OutputStream _out, OutputStream _err, boolean _show, int _procNumber) { + out = _out; + err = _err; + show = _show; + maxProcesses = _procNumber; + processes = new ProcessLauncher[maxProcesses]; + } + + /** + * Returns maximum number of processes + */ + public int getMaxProcesses() { + return maxProcesses; + } + + /** + * Performs an attempt to launch new process. Returns BuildProcessLauncher + * if it was successfully launched, null if there is no room for it yet in + * the process pool. + * + * @param cmd Command to launch + * @param cwd Command working directory + * @param monitor Progress monitor for this task + */ + public ProcessLauncher launchProcess(IBuildCommand cmd, IPath cwd, IProgressMonitor monitor) { + if (hasEmpty()) { + int i = 0; + for (; i < maxProcesses; i++) { + if (processes[i] == null || processes[i].queryState() == ProcessLauncher.STATE_DONE) { + break; + } + } + + if (i < maxProcesses) { + processes[i] = new ProcessLauncher(cmd.getCommand(), cmd.getArgs(), mapToStringArray(cmd.getEnvironment()), cwd, out, err, monitor, show); + processes[i].launch(); + return processes[i]; + } + } + return null; + } + + /** + * Checks states of all currently running processes. If it finds + * one with state other than STATE_DONE or STATE_RUNNING, it is + * returned as a result. Otherwise this method returns null. + */ + public ProcessLauncher queryStates() { + ProcessLauncher result = null; + + for (int i = 0; i < maxProcesses; i++) { + if (processes[i] != null) { + int state = processes[i].queryState(); + if (state != ProcessLauncher.STATE_RUNNING) { + if (state != ProcessLauncher.STATE_DONE && result == null) + result = processes[i]; + } + } + } + + return result; + } + + /** + * Checks states of all currently running processes. + */ + public boolean hasEmpty() { + for (int i = 0; i < maxProcesses; i++) { + if (processes[i] == null) + return true; + else { + if (processes[i].queryState() != ProcessLauncher.STATE_RUNNING) + return true; + } + } + return false; + } + + + /** + * Converts map to strings array + */ + protected String[] mapToStringArray(Map map){ + if(map == null) + return null; + + List list = new ArrayList(); + + for(Iterator iter = map.entrySet().iterator(); iter.hasNext();){ + Map.Entry entry = (Map.Entry)iter.next(); + list.add((String)entry.getKey() + "=" + (String)entry.getValue()); //$NON-NLS-1$ + } + + return (String[])list.toArray(new String[list.size()]); + } + + /** + * + * @return + */ + static public int checkCPUNumber() { + if (procNumber > 0) return procNumber; + + procNumber = 1; + int x = 0; + String os = System.getProperty("os.name"); //$NON-NLS-1$ + if (os != null) { + if (os.startsWith("Win")) { //$NON-NLS-1$ + try { + x = new Integer(System.getenv("NUMBER_OF_PROCESSORS")).intValue(); //$NON-NLS-1$ + if (x > 0) { procNumber = x; } + } catch (NumberFormatException e) {} // fallthrough and return default + } else { // linux + String p = "/proc/cpuinfo"; //$NON-NLS-1$ + try { + BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(p))); + String s; + while ((s = r.readLine() ) != null ) + { if (s.startsWith("processor\t:")) x++; } //$NON-NLS-1$ + r.close(); + if (x > 0) { procNumber = x; } + } + catch (IOException e) {} // fallthrough and return default + } + } + if(DbgUtil.DEBUG) + DbgUtil.trace("Number of processors detected: " + procNumber); //$NON-NLS-1$ + return procNumber; + } +} diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/ParallelBuilder.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/ParallelBuilder.java new file mode 100644 index 00000000000..54131325d08 --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/ParallelBuilder.java @@ -0,0 +1,483 @@ +/******************************************************************************* + * Copyright (c) 2006 Intel Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Intel Corporation - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.managedbuilder.internal.buildmodel; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.managedbuilder.buildmodel.IBuildCommand; +import org.eclipse.cdt.managedbuilder.buildmodel.IBuildDescription; +import org.eclipse.cdt.managedbuilder.buildmodel.IBuildResource; +import org.eclipse.cdt.managedbuilder.buildmodel.IBuildStep; +import org.eclipse.cdt.managedbuilder.core.IConfiguration; +import org.eclipse.cdt.managedbuilder.internal.core.Configuration; +import org.eclipse.cdt.managedbuilder.internal.core.ManagedMakeMessages; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; + +/** + * This is the main class for parallel internal builder implementation + * + * NOTE: This class is subject to change and discuss, + * and is currently available in experimental mode only + */ +public class ParallelBuilder { + public static final int STATUS_OK = 0; + public static final int STATUS_ERROR = 1; + public static final int STATUS_CANCELED = 2; + public static final int STATUS_INVALID = -1; + public static final long MAIN_LOOP_DELAY = 50L; + + private static final String BUILDER_MSG_HEADER = "InternalBuilder.msg.header"; //$NON-NLS-1$ + private static final String LINE_SEPARATOR = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ + + public static int lastThreadsUsed = 0; // use externally for report purposes only + + protected IPath cwd; + protected GenDirInfo dirs; + protected IProgressMonitor monitor; + protected OutputStream out; + protected OutputStream err; + protected boolean resumeOnErrors; + protected boolean buildIncrementally; + protected HashSet unsorted = new HashSet(); + protected HashMap queueHash = new HashMap(); + protected LinkedList queue = new LinkedList(); + + /** + * This class implements queue element + */ + protected class BuildQueueElement implements Comparable { + protected IBuildStep step; + protected int level; + + public BuildQueueElement(IBuildStep _step, int _level) { + step = _step; + level = _level; + } + + public IBuildStep getStep() { + return step; + } + + public int getLevel() { + return level; + } + + public void setLevel(int _level) { + level = _level; + } + + public int hashCode() { + return step.hashCode(); + } + + public int compareTo(Object obj) { + if (obj == null) + throw new NullPointerException(); + BuildQueueElement elem = (BuildQueueElement)obj; + + if (elem.getLevel() > level) + return -1; + if (elem.getLevel() < level) + return 1; + return 0; + } + + /** + * Updates level value + * + * @param _step + * @param _level + */ + public boolean check(IBuildStep _step, int _level) { + if (level < _level && step.equals(_step)) { + level = _level; + return true; + } else { return false; } + } + + public String toString() { + return"[BuildQueueElement] " + DbgUtil.stepName(step) + " @ " + level; //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + /** + * This class stores information about step being built + */ + protected class ActiveBuildStep { + protected IPath stepCwd; + protected GenDirInfo stepDirs; + protected IBuildStep step; + protected IBuildCommand[] cmds; + protected int activeCmd; + protected boolean done; + protected ProcessLauncher launcher; + + public ActiveBuildStep(IBuildStep _step) { + step = _step; + + if(dirs == null) + stepDirs = new GenDirInfo(step.getBuildDescription().getConfiguration()); + else + stepDirs = dirs; + if (cwd == null) + stepCwd = step.getBuildDescription().getDefaultBuildDirLocation(); + else + stepCwd = cwd; + cmds = step.getCommands(stepCwd, null, null, true); + activeCmd = -1; + done = false; + createOutDirs(); + } + + public boolean launchNextCmd(BuildProcessManager mgr) { + if (monitor.isCanceled()) { + done = true; + return false; + } + if (activeCmd + 1 >= cmds.length) + done = true; + else { + IBuildCommand cmd = cmds[++activeCmd]; + launcher = mgr.launchProcess(cmd, stepCwd, monitor); + if (launcher != null) return true; + activeCmd--; + done = true; // temporary + } + return false; + } + + public boolean isDone() { + return done; + } + + public IBuildStep getStep() { + return step; + } + + public ProcessLauncher getLauncher() { + return launcher; + } + protected void createOutDirs(){ + IBuildResource rcs[] = step.getOutputResources(); + + for(int i = 0; i < rcs.length; i++){ + dirs.createDir(rcs[i], new NullProgressMonitor()); + } + } + } + + /** + * Build process is divided into following steps: + * 1. Resources enqueueing & levelling + * 2. Queue sorting + * 3. Queue dispatching + * + * @param des Build description + * @param cwd Working directory + * @param dirs GenDirInfo? + * @param out Output stream + * @param err Error output stream + * @param monitor Progress monitor + * @param resumeOnErrors If true, build process will not stop when + * compilation errors encountered + */ + static public int build(IBuildDescription des, IPath cwd, GenDirInfo dirs, OutputStream out, OutputStream err, IProgressMonitor monitor, boolean resumeOnErrors, boolean buildIncrementally) { + IConfiguration cfg = des.getConfiguration(); + if(dirs == null) dirs = new GenDirInfo(cfg); + if(cwd == null) cwd = des.getDefaultBuildDirLocation(); + int threads = 1; + if (cfg instanceof Configuration) { + if (((Configuration)cfg).getParallelDef()) + threads = BuildProcessManager.checkCPUNumber(); + else + threads = ((Configuration)cfg).getParallelNumber(); + } + ParallelBuilder builder = new ParallelBuilder(cwd, dirs, out, err, monitor, resumeOnErrors, buildIncrementally); + builder.enqueueAll(des); + builder.sortQueue(); + monitor.beginTask("", builder.queue.size()); //$NON-NLS-1$ + builder.dispatch(new BuildProcessManager(out, err, true, threads)); + monitor.done(); + lastThreadsUsed = threads; + return IBuildModelBuilder.STATUS_OK; + } + + /** + * Initializes parallel builder + */ + protected ParallelBuilder(IPath _cwd, GenDirInfo _dirs, OutputStream _out, OutputStream _err, IProgressMonitor _monitor, boolean _resumeOnErrors, boolean _buildIncrementally) { + cwd = _cwd; + dirs = _dirs; + out = _out; + err = _err; + monitor = _monitor; + resumeOnErrors = _resumeOnErrors; + buildIncrementally = _buildIncrementally; + } + + /** + * Enqueues build steps, calculating their levels + */ + protected void enqueueAll(IBuildDescription des) { + enqueueSteps(des.getInputStep(), 0); + } + + /** + * Sorts the queue + */ + protected void sortQueue() { + Iterator iter = unsorted.iterator(); + while (iter.hasNext()) { + queue.add(iter.next()); + } + unsorted.clear(); + unsorted = null; + queueHash.clear(); + queueHash = null; + + Collections.sort(queue); + } + + /** + * Enqueues build steps directly accessed from the given one. Each + * new element will have level 1 if it needs rebuild and 0 otherwise. + */ + protected void enqueueSteps(IBuildStep step, int level) { + IBuildResource[] resources = step.getOutputResources(); + + for (int i = 0; i < resources.length; i++) { + IBuildStep steps[] = resources[i].getDependentSteps(); + for (int j = 0; j < steps.length; j++) { + IBuildStep st = steps[j]; + if (st != null && st.getBuildDescription().getOutputStep() != st) { + BuildQueueElement b = (BuildQueueElement)queueHash.get(st); + if (b != null){ + if (b.level < level) b.setLevel(level); + } else { + //TODO: whether we need check isRemoved & needRebuild ? + if (!steps[j].isRemoved() && (!buildIncrementally || steps[j].needsRebuild())) { + addElement(steps[j], level); + } + enqueueSteps(steps[j], level + 1); + } + } + } + } + } + + /** + * Adds new element to the build queue and step<->element hash map + */ + protected void addElement(IBuildStep step, int level) { + BuildQueueElement elem = new BuildQueueElement(step, level); + unsorted.add(elem); + queueHash.put(step, elem); + } + + /** + * Dispatches the build queue and returns build status + */ + protected int dispatch(BuildProcessManager mgr) { + ActiveBuildStep[] active = new ActiveBuildStep[mgr.getMaxProcesses()]; + for (int i = 0; i < active.length; i++) { + active[i] = null; // new ActiveBuildStep(); + } + + int activeCount = 0; + int maxLevel = 0; + int status = STATUS_OK; + String errorMsg = null; + + // Going into "infinite" main loop + main_loop: + while (true) { + if (monitor.isCanceled()) { + status = STATUS_CANCELED; + errorMsg = CCorePlugin.getResourceString("CommandLauncher.error.commandCanceled"); //$NON-NLS-1$ + break main_loop; + } + // Check build process states + ProcessLauncher launcher = mgr.queryStates(); + if (launcher != null) { + // Build process has been canceled or failed to launch + if (launcher.queryState() == ProcessLauncher.STATE_CANCELED) + status = STATUS_CANCELED; + else + status = STATUS_INVALID; + errorMsg = launcher.getErrorMessage(); + break main_loop; + } + // Everything goes OK. + boolean proceed = true; + + // Check if there is room for new process + if (!mgr.hasEmpty()) { + proceed = false; + } else { + // Check "active steps" list for completed ones + for (int i = 0; i < active.length; i++) { + if (active[i] == null) continue; + ProcessLauncher pl = active[i].getLauncher(); + if (pl == null) continue; + if (pl.queryState() == ProcessLauncher.STATE_DONE) { + // If process has terminated with error, break loop + // (except resumeOnErrors == true) + + if (!resumeOnErrors && pl.getExitCode() != 0) { + status = STATUS_ERROR; + break main_loop; + } + // Try to launch next command for the current active step + if (active[i].isDone()) continue; + if (active[i].launchNextCmd(mgr)) { + // Command has been launched. Check if process pool is not maximized yet + if (!mgr.hasEmpty()) { + proceed = false; + break; + } + } else { + // Command has not been launched: step complete + refreshOutputs(active[i].getStep()); + activeCount--; + monitor.worked(1); + } + } + } + } + + // If nothing to do, then sleep and continue main loop + if (!proceed) { + try { + Thread.sleep(MAIN_LOOP_DELAY); + } catch (InterruptedException e) { + // do nothing + } + continue main_loop; + } + + // Check if we need to schedule another process + if (queue.size() != 0 && activeCount < active.length) { + // Need to schedule another process + Iterator iter = queue.iterator(); + + // Iterate over build queue + while (iter.hasNext()) { + BuildQueueElement elem = (BuildQueueElement)iter.next(); + + // If "active steps" list is full, then break loop + if (activeCount == active.length) + break; + + // If current element's level exceeds maximum level of currently built + // resources, then stop iteration (we can not build it anyway) + if (elem.getLevel() > maxLevel + 1) + break; + + //Check if all prerequisites are built + IBuildResource[] res = elem.getStep().getInputResources(); + boolean prereqBuilt = true; + for (int j = 0; j < res.length; j++) { + IBuildStep stp = res[j].getProducerStep(); // step which produces input for curr + boolean built = true; + if (stp != stp.getBuildDescription().getInputStep()) { + for (int k = 0; k < active.length; k++) { + if (active[k] != null && active[k].getStep().equals(stp) && !active[k].isDone()) { + built = false; + break; + } + } + } + if (!built) { + prereqBuilt = false; + break; + } + } + + if (prereqBuilt) { + // All prereqs are built + IBuildStep step = elem.getStep(); + + // Remove element from the build queue and add it to the + // "active steps" list. + iter.remove(); + for (int i = 0; i < active.length; i++) { + if (active[i] == null || active[i].isDone()) { + active[i] = new ActiveBuildStep(step); + if (active[i].launchNextCmd(mgr)) activeCount++; + break; + } + } + + // Update maxLevel + if (elem.getLevel() > maxLevel) + maxLevel = elem.getLevel(); + // We don't need to start new process immediately since + // it will be done on the next main loop iteration + } + } + } + + // Now finally, check if we're done + if (activeCount <= 0 && queue.size() == 0) + break main_loop; + } + + if (status != STATUS_OK && errorMsg != null) + printMessage(errorMsg, out); + return status; + } + + /** + * Prints output to the console + */ + protected void printMessage(String msg, OutputStream out) { + if (out != null) { + msg = ManagedMakeMessages.getFormattedString(BUILDER_MSG_HEADER, msg) + LINE_SEPARATOR; + try { + out.write(msg.getBytes()); + out.flush(); + } catch (IOException e) { + // do nothing + } + } + } + + /** + * Updates info about generated files (after step completed) + * @param step + */ + protected void refreshOutputs(IBuildStep step){ + IProgressMonitor mon = new NullProgressMonitor(); + IBuildResource outres[] = step.getOutputResources(); + IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); + for(int i = 0; i < outres.length; i++){ + IPath path = outres[i].getFullPath(); + if(path != null){ + try { root.getFile(path).refreshLocal(0, mon); } + catch (CoreException e) {} + } + } + } + + +} diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/ProcessLauncher.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/ProcessLauncher.java new file mode 100644 index 00000000000..3d06f7ac536 --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/buildmodel/ProcessLauncher.java @@ -0,0 +1,189 @@ +/******************************************************************************* + * Copyright (c) 2006 Intel Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Intel Corporation - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.managedbuilder.internal.buildmodel; + +import java.io.*; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.internal.core.ProcessClosure; +import org.eclipse.cdt.utils.spawner.ProcessFactory; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; + +/** + * This class implements external process launching for internal builder. + * + * NOTE: This class is subject to change and discuss, + * and is currently available in experimental mode only + */ +public class ProcessLauncher { + public final static int STATE_DONE = 0; + public final static int STATE_RUNNING = 1; + public final static int STATE_CANCELED = 2; + public final static int STATE_ILLEGAL = -1; + + protected String[] cmd; + protected String[] env; + protected File cwd; + protected OutputStream out; + protected OutputStream err; + protected IProgressMonitor monitor; + protected boolean show; + protected String error; + protected String lineSeparator; + protected Process process; + protected ProcessClosure closure = null; + protected int state; + + /** + * Returns command line as a string array + */ + public String[] getCommandArray() { + return cmd; + } + + /** + * Returns command line in a single string + */ + public String getCommandLine() { + StringBuffer buf = new StringBuffer(); + if (cmd != null) { + for (int i = 0; i < cmd.length; i++) { + buf.append(cmd[i]); + buf.append(' '); + } + buf.append(lineSeparator); + } + + return buf.toString(); + } + + /** + * Returns process environment + */ + public String[] getEnvironment() { + return env; + } + + /** + * Returns command working directory + */ + public File getWorkingDir() { + return cwd; + } + + /** + * Returns error message (if any) + */ + public String getErrorMessage() { + return error; + } + + /** + * Returns exit code of a process + */ + public int getExitCode() { + if (process == null || closure.isAlive()) return 0; + try { return process.waitFor(); } + catch (InterruptedException e) { return 0; } + } + + /** + * Initializes launcher + * @param _cmd Command path + * @param args Command arguments + * @param _env Environment + * @param _cwd Working directory + * @param _out Output stream + * @param _err Error output stream + * @param _monitor Progress monitor + * @param _show If true, print command line before launching + */ + public ProcessLauncher(IPath _cmd, String[] args, String[] _env, IPath _cwd, OutputStream _out, OutputStream _err, IProgressMonitor _monitor, boolean _show) { + cmd = createCmdArray(_cmd.toOSString(), args); + env = _env; + cwd = _cwd.toFile(); + out = _out; + err = _err; + monitor = _monitor; + show = _show; + error = ""; //$NON-NLS-1$ + lineSeparator = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ + } + + /** + * Launches a process + */ + public void launch() { + try { + if (show) + printCommandLine(); + state = STATE_RUNNING; + process = ProcessFactory.getFactory().exec(cmd, env, cwd); + closure = new ProcessClosure(process, out, err); + // Close the input of the process since we will never write to it + try { + process.getOutputStream().close(); + } catch (IOException e) { + // do nothing + } + closure.runNonBlocking(); + } catch (IOException e) { + error = e.getMessage(); + closure = null; + } + } + + /** + * Returns process state + */ + public int queryState() { + if (state == STATE_RUNNING) { + if (closure == null) + state = STATE_ILLEGAL; + else if (monitor.isCanceled()) { + closure.terminate(); + error = CCorePlugin.getResourceString("CommandLauncher.error.commandCanceled"); //$NON-NLS-1$ + state = STATE_CANCELED; + } else if (!closure.isRunning()) { + state = STATE_DONE; + } + } + + return state; + } + + /** + * Creates a string array representing the command that will be passed + * to the process + */ + protected String[] createCmdArray(String cmdPath, String[] cmdArgs) { + String[] args = new String[1 + cmdArgs.length]; + args[0] = cmdPath; + System.arraycopy(cmdArgs, 0, args, 1, cmdArgs.length); + + return args; + } + + /** + * Prints command line + */ + protected void printCommandLine() { + if (out != null) { + try { + out.write(getCommandLine().getBytes()); + out.flush(); + } catch (IOException e) { + // do nothing + } + } + } +} diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Configuration.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Configuration.java index 4cc276d59d4..4b465707d5e 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Configuration.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Configuration.java @@ -37,6 +37,7 @@ import org.eclipse.cdt.managedbuilder.core.IToolChain; import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin; import org.eclipse.cdt.managedbuilder.envvar.IConfigurationEnvironmentVariableSupplier; +import org.eclipse.cdt.managedbuilder.internal.buildmodel.BuildProcessManager; import org.eclipse.cdt.managedbuilder.internal.envvar.EnvironmentVariableProvider; import org.eclipse.cdt.managedbuilder.internal.envvar.UserDefinedEnvironmentSupplier; import org.eclipse.cdt.managedbuilder.internal.macros.BuildMacroProvider; @@ -113,15 +114,27 @@ public class Configuration extends BuildObject implements IConfiguration { //as a special Builder object of the tool-chain and implement the internal //builder enabling/disabling as the Builder substitution functionality // - private static final String INTERNAL_BUILDER = "internalBuilder"; + private static final String INTERNAL_BUILDER = "internalBuilder"; //$NON-NLS-1$ //preference key that holds the Internal Builder enable state private static final String INTERNAL_BUILDER_ENABLED = "enabled"; //$NON-NLS-1$ //preference key that holds the internal builder mode private static final String INTERNAL_BUILDER_IGNORE_ERR = "ignoreErr"; //$NON-NLS-1$ + //preference key that holds the internal builder mode + private static final String INTERNAL_BUILDER_PARALLEL = "parallel"; //$NON-NLS-1$ + //preference key that holds the internal builder mode + private static final String INTERNAL_BUILDER_PARALLEL_DEF = "paralleldef"; //$NON-NLS-1$ + //preference key that holds the internal builder mode + private static final String INTERNAL_BUILDER_PARALLELNUMBER = "parallelnumber"; //$NON-NLS-1$ //Internal Builder enable state private boolean internalBuilderEnabled; //Internal Builder mode private boolean internalBuilderIgnoreErr = true; + //Internal Builder parallel mode + private boolean internalBuilderParallel = true; + //Internal Builder parallel mode - default jobs # + private boolean internalBuilderParallelDef = true; + //Number of parallel threads + private int internalBuilderParallelNumber = 1; // default value /* @@ -335,6 +348,9 @@ public class Configuration extends BuildObject implements IConfiguration { enableInternalBuilder(cloneConfig.isInternalBuilderEnabled()); setInternalBuilderIgnoreErr(cloneConfig.getInternalBuilderIgnoreErr()); + setInternalBuilderParallel(cloneConfig.getInternalBuilderParallel()); + setParallelDef(cloneConfig.getParallelDef()); + setParallelNumber(cloneConfig.getParallelNumber()); // internalBuilderEnabled = cloneConfig.internalBuilderEnabled; // internalBuilderIgnoreErr = cloneConfig.internalBuilderIgnoreErr; @@ -1741,6 +1757,22 @@ public class Configuration extends BuildObject implements IConfiguration { * */ + public void setInternalBuilderBoolean(boolean value, String pref) { + Preferences prefs = getPreferences(INTERNAL_BUILDER); + if(prefs != null){ + prefs.putBoolean(pref, value); + try { + prefs.flush(); + } catch (BackingStoreException e) {} + } + } + + public boolean getInternalBuilderBoolean(String pref, boolean defaultValue) { + Preferences prefs = getPreferences(INTERNAL_BUILDER); + return prefs != null ? + prefs.getBoolean(pref, false) : defaultValue; + } + /* * this method is used for enabling/disabling the internal builder * for the given configuration @@ -1750,28 +1782,16 @@ public class Configuration extends BuildObject implements IConfiguration { public void enableInternalBuilder(boolean enable){ // if(internalBuilderEnabled != enable){ internalBuilderEnabled = enable; - Preferences prefs = getPreferences(INTERNAL_BUILDER); - if(prefs != null){ - prefs.putBoolean(INTERNAL_BUILDER_ENABLED, enable); - try { - prefs.flush(); - } catch (BackingStoreException e) { - } - } + setInternalBuilderBoolean(enable, INTERNAL_BUILDER_ENABLED); // } } /* * returns whether the internal builder is enabled - * * @return boolean */ public boolean isInternalBuilderEnabled(){ - Preferences prefs = getPreferences(INTERNAL_BUILDER); - - return prefs != null ? - prefs.getBoolean(INTERNAL_BUILDER_ENABLED, false) : - internalBuilderEnabled; + return getInternalBuilderBoolean(INTERNAL_BUILDER_ENABLED, internalBuilderEnabled); } /* @@ -1785,14 +1805,7 @@ public class Configuration extends BuildObject implements IConfiguration { public void setInternalBuilderIgnoreErr(boolean ignore){ // if(internalBuilderIgnoreErr != ignore){ internalBuilderIgnoreErr = ignore; - Preferences prefs = getPreferences(INTERNAL_BUILDER); - if(prefs != null){ - prefs.putBoolean(INTERNAL_BUILDER_IGNORE_ERR, ignore); - try { - prefs.flush(); - } catch (BackingStoreException e) { - } - } + setInternalBuilderBoolean(ignore, INTERNAL_BUILDER_IGNORE_ERR); // } } @@ -1804,11 +1817,74 @@ public class Configuration extends BuildObject implements IConfiguration { * @return boolean */ public boolean getInternalBuilderIgnoreErr(){ + return getInternalBuilderBoolean(INTERNAL_BUILDER_IGNORE_ERR, internalBuilderIgnoreErr); + } + + /** + * + * sets the Internal Builder Parallel mode + * + * @param parallel if true, internal builder will use parallel mode + */ + public void setInternalBuilderParallel(boolean parallel){ + internalBuilderParallel = parallel; + setInternalBuilderBoolean(parallel, INTERNAL_BUILDER_PARALLEL); + } + + /** + * returns the Internal Builder parallel mode + * if true, internal builder will work in parallel mode + * otherwise it will use only one thread + * + * @return boolean + */ + public boolean getInternalBuilderParallel(){ + return getInternalBuilderBoolean(INTERNAL_BUILDER_PARALLEL, internalBuilderParallel); + } + + /** + * @param parallel if true, internal builder will use parallel mode + */ + public void setParallelDef(boolean parallel_def){ + internalBuilderParallelDef = parallel_def; + setInternalBuilderBoolean(parallel_def, INTERNAL_BUILDER_PARALLEL_DEF); + } + + /** + * @return boolean + */ + public boolean getParallelDef(){ + return getInternalBuilderBoolean(INTERNAL_BUILDER_PARALLEL_DEF, internalBuilderParallelDef); + } + + /** + * + * sets number of Parallel threads + * + * @param int + */ + public void setParallelNumber(int n){ + internalBuilderParallelNumber = n; Preferences prefs = getPreferences(INTERNAL_BUILDER); - - return prefs != null ? - prefs.getBoolean(INTERNAL_BUILDER_IGNORE_ERR, true) : - internalBuilderIgnoreErr; + if(prefs != null){ + prefs.putInt(INTERNAL_BUILDER_PARALLELNUMBER, n); + try { prefs.flush(); } + catch (BackingStoreException e) {} + } + } + + /** + * returns number of Parallel threads + * + * @return int + */ + public int getParallelNumber(){ + Preferences prefs = getPreferences(INTERNAL_BUILDER); + int cpus = BuildProcessManager.checkCPUNumber(); + int x = prefs != null ? + prefs.getInt(INTERNAL_BUILDER_PARALLELNUMBER, cpus) : + internalBuilderParallelNumber; + return (x > 0) ? x : 1; } private Preferences getPreferences(String name){ diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/GeneratedMakefileBuilder.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/GeneratedMakefileBuilder.java index f57b2f01c98..ea89f9de87d 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/GeneratedMakefileBuilder.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/GeneratedMakefileBuilder.java @@ -40,6 +40,7 @@ import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.cdt.managedbuilder.envvar.IBuildEnvironmentVariable; import org.eclipse.cdt.managedbuilder.internal.buildmodel.DescriptionBuilder; import org.eclipse.cdt.managedbuilder.internal.buildmodel.IBuildModelBuilder; +import org.eclipse.cdt.managedbuilder.internal.buildmodel.ParallelBuilder; import org.eclipse.cdt.managedbuilder.internal.buildmodel.StepBuilder; import org.eclipse.cdt.managedbuilder.macros.BuildMacroException; import org.eclipse.cdt.managedbuilder.macros.IBuildMacroProvider; @@ -1186,6 +1187,9 @@ public class GeneratedMakefileBuilder extends ACBuilder { boolean buildIncrementaly, boolean resumeOnErr, IProgressMonitor monitor) { + + boolean isParallel = ((Configuration)cfg).getInternalBuilderParallel(); + // Get the project and make sure there's a monitor to cancel the build IProject currentProject = cfg.getOwner().getProject(); if (monitor == null) { @@ -1196,9 +1200,6 @@ public class GeneratedMakefileBuilder extends ACBuilder { msgs[0] = ManagedMakeMessages.getResourceString(INTERNAL_BUILDER); msgs[1] = currentProject.getName(); - monitor.beginTask("", 1000); //$NON-NLS-1$ - monitor.subTask(ManagedMakeMessages.getFormattedString(MAKE, msgs)); - ConsoleOutputStream consoleOutStream = null; IConsole console = null; OutputStream epmOutputStream = null; @@ -1212,8 +1213,10 @@ public class GeneratedMakefileBuilder extends ACBuilder { } IBuildDescription des = BuildDescriptionManager.createBuildDescription(cfg, delta, flags); - - DescriptionBuilder builder = new DescriptionBuilder(des, buildIncrementaly, resumeOnErr); + + DescriptionBuilder builder = null; + if (!isParallel) + builder = new DescriptionBuilder(des, buildIncrementaly, resumeOnErr); // Get a build console for the project StringBuffer buf = new StringBuffer(); @@ -1244,7 +1247,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { consoleOutStream.write(buf.toString().getBytes()); consoleOutStream.flush(); - if(builder.getNumCommands() > 0) { + if(isParallel || builder.getNumCommands() > 0) { // Remove all markers for this project removeAllMarkers(currentProject); @@ -1256,8 +1259,15 @@ public class GeneratedMakefileBuilder extends ACBuilder { // until we explicitly close it. See bug#123302. epmOutputStream = epm.getOutputStream(); - int status = builder.build(epmOutputStream, epmOutputStream, new SubProgressMonitor(monitor, 1000)); - + int status = 0; + + long t1 = System.currentTimeMillis(); + if (isParallel) + status = ParallelBuilder.build(des, null, null, epmOutputStream, epmOutputStream, monitor, resumeOnErr, buildIncrementaly); + else + status = builder.build(epmOutputStream, epmOutputStream, monitor); + long t2 = System.currentTimeMillis(); + // Report either the success or failure of our mission buf = new StringBuffer(); @@ -1284,7 +1294,16 @@ public class GeneratedMakefileBuilder extends ACBuilder { break; } buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$//$NON-NLS-2$ - + + // Report time and number of threads used + buf.append("Time consumed: "); + buf.append(t2 - t1); + buf.append(" ms. "); + if (isParallel) { + buf.append("Parallel threads used: "); + buf.append(ParallelBuilder.lastThreadsUsed); + } + buf.append("\n"); // Write message on the console consoleOutStream.write(buf.toString().getBytes()); consoleOutStream.flush(); diff --git a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/BuildSettingsBlock.java b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/BuildSettingsBlock.java index a44998b3f37..bd3f0f72ade 100644 --- a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/BuildSettingsBlock.java +++ b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/BuildSettingsBlock.java @@ -17,6 +17,7 @@ import java.util.regex.Pattern; import org.eclipse.cdt.managedbuilder.core.IBuilder; import org.eclipse.cdt.managedbuilder.core.IConfiguration; import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; +import org.eclipse.cdt.managedbuilder.internal.buildmodel.BuildProcessManager; import org.eclipse.cdt.managedbuilder.internal.core.Configuration; import org.eclipse.cdt.managedbuilder.internal.macros.BuildMacroProvider; import org.eclipse.cdt.managedbuilder.ui.properties.BuildPropertyPage; @@ -37,9 +38,11 @@ import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Spinner; import org.eclipse.swt.widgets.Text; public class BuildSettingsBlock extends AbstractCOptionPage { @@ -60,6 +63,11 @@ public class BuildSettingsBlock extends AbstractCOptionPage { private static final String INTERNAL_BUILDER_GROUP = LABEL + ".internal.builder.group"; //$NON-NLS-1$ private static final String INTERNAL_BUILDER_ENABLE_BTN = LABEL + ".internal.builder.enable"; //$NON-NLS-1$ private static final String INTERNAL_BUILDER_IGNORE_ERR_BTN = LABEL + ".internal.builder.ignore.err"; //$NON-NLS-1$ + private static final String INTERNAL_BUILDER_PARALLEL = LABEL + ".internal.builder.parallel.head"; //$NON-NLS-1$ + private static final String INTERNAL_BUILDER_PARALLEL_BTN = LABEL + ".internal.builder.parallel.use"; //$NON-NLS-1$ + private static final String INTERNAL_BUILDER_PARALLEL_DEF = LABEL + ".internal.builder.parallel.default"; //$NON-NLS-1$ + private static final String INTERNAL_BUILDER_PARALLEL_NUM = LABEL + ".internal.builder.parallel.number"; //$NON-NLS-1$ + private static final String INTERNAL_BUILDER_PARALLEL_TOOLTIP = LABEL + ".internal.builder.parallel.tooltip"; //$NON-NLS-1$ private static final String INTERNAL_BUILDER_EXPERIMENTAL_NOTE = LABEL + ".internal.builder.experimental.note"; //$NON-NLS-1$ private static final String EMPTY_STRING = new String(); @@ -77,6 +85,11 @@ public class BuildSettingsBlock extends AbstractCOptionPage { protected Group internalBuilderGroup; protected Button internalBuilderEnable; protected Button internalBuilderIgnoreErr; + protected Button internalBuilderParallel; + protected Button internalBuilderParallelDef1; + protected Button internalBuilderParallelDef2; + protected Spinner parallelProcesses; + protected final int cpuNumber = BuildProcessManager.checkCPUNumber(); /* * Bookeeping variables @@ -296,18 +309,17 @@ public class BuildSettingsBlock extends AbstractCOptionPage { internalBuilderGroup = new Group(parent, SWT.NONE); internalBuilderGroup.setFont(parent.getFont()); internalBuilderGroup.setText(ManagedBuilderUIMessages.getResourceString(INTERNAL_BUILDER_GROUP)); - internalBuilderGroup.setLayout(new GridLayout(1, true)); + internalBuilderGroup.setLayout(new GridLayout(2, false)); internalBuilderGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - + Label dotLabel = new Label(internalBuilderGroup, SWT.CENTER); dotLabel.setFont(internalBuilderGroup.getFont()); dotLabel.setText(ManagedBuilderUIMessages.getResourceString(INTERNAL_BUILDER_EXPERIMENTAL_NOTE)); - - internalBuilderEnable = new Button(internalBuilderGroup, SWT.CHECK | SWT.LEFT); - internalBuilderEnable.setFont(internalBuilderGroup.getFont()); - internalBuilderEnable.setText(ManagedBuilderUIMessages.getResourceString(INTERNAL_BUILDER_ENABLE_BTN)); - internalBuilderEnable.setBackground(internalBuilderGroup.getBackground()); - internalBuilderEnable.setForeground(internalBuilderGroup.getForeground()); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 2; + dotLabel.setLayoutData(gd); + + internalBuilderEnable = createInternalBuilderButton(ManagedBuilderUIMessages.getResourceString(INTERNAL_BUILDER_ENABLE_BTN), 2); internalBuilderEnable.addSelectionListener(new SelectionAdapter () { public void widgetSelected(SelectionEvent e) { Configuration config = (Configuration)BuildSettingsBlock.this.parent.getSelectedConfigurationClone(); @@ -322,11 +334,7 @@ public class BuildSettingsBlock extends AbstractCOptionPage { } }); - internalBuilderIgnoreErr = new Button(internalBuilderGroup, SWT.CHECK | SWT.LEFT); - internalBuilderIgnoreErr.setFont(internalBuilderGroup.getFont()); - internalBuilderIgnoreErr.setText(ManagedBuilderUIMessages.getResourceString(INTERNAL_BUILDER_IGNORE_ERR_BTN)); - internalBuilderIgnoreErr.setBackground(internalBuilderGroup.getBackground()); - internalBuilderIgnoreErr.setForeground(internalBuilderGroup.getForeground()); + internalBuilderIgnoreErr = createInternalBuilderButton(ManagedBuilderUIMessages.getResourceString(INTERNAL_BUILDER_IGNORE_ERR_BTN), 2); internalBuilderIgnoreErr.addSelectionListener(new SelectionAdapter () { public void widgetSelected(SelectionEvent e) { Configuration config = (Configuration)BuildSettingsBlock.this.parent.getSelectedConfigurationClone(); @@ -341,8 +349,108 @@ public class BuildSettingsBlock extends AbstractCOptionPage { } }); + Label parallelLabel = new Label(internalBuilderGroup, SWT.CENTER); + parallelLabel.setFont(internalBuilderGroup.getFont()); + parallelLabel.setBackground(internalBuilderGroup.getBackground()); + parallelLabel.setForeground(internalBuilderGroup.getForeground()); + parallelLabel.setText(ManagedBuilderUIMessages.getResourceString(INTERNAL_BUILDER_PARALLEL)); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 2; + parallelLabel.setLayoutData(gd); + + internalBuilderParallel = createInternalBuilderButton(ManagedBuilderUIMessages.getResourceString(INTERNAL_BUILDER_PARALLEL_BTN), 2); + internalBuilderParallel.addSelectionListener(new SelectionAdapter () { + public void widgetSelected(SelectionEvent e) { + Configuration config = (Configuration)BuildSettingsBlock.this.parent.getSelectedConfigurationClone(); + config.setInternalBuilderParallel(internalBuilderParallel.getSelection()); + setValues(); + setDirty(true); + } + }); + internalBuilderParallel.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent event) { internalBuilderParallel = null; } + }); + + internalBuilderParallelDef1 = new Button(internalBuilderGroup, SWT.RADIO); + internalBuilderParallelDef1.setFont(internalBuilderGroup.getFont()); + internalBuilderParallelDef1.setBackground(internalBuilderGroup.getBackground()); + internalBuilderParallelDef1.setForeground(internalBuilderGroup.getForeground()); + internalBuilderParallelDef1.setText("Use optimal jobs number"); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 2; + gd.horizontalIndent = 15; + internalBuilderParallelDef1.setLayoutData(gd); + internalBuilderParallelDef1.setSelection(true); + + internalBuilderParallelDef1.addSelectionListener(new SelectionAdapter () { + public void widgetSelected(SelectionEvent e) { + Configuration config = (Configuration)BuildSettingsBlock.this.parent.getSelectedConfigurationClone(); + config.setParallelDef(internalBuilderParallelDef1.getSelection()); + setValues(); + setDirty(true); + } + }); + + internalBuilderParallelDef1.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent event) { internalBuilderParallelDef1 = null; } + }); + + internalBuilderParallelDef2 = new Button(internalBuilderGroup, SWT.RADIO); + internalBuilderParallelDef2.setFont(internalBuilderGroup.getFont()); + internalBuilderParallelDef2.setBackground(internalBuilderGroup.getBackground()); + internalBuilderParallelDef2.setForeground(internalBuilderGroup.getForeground()); + internalBuilderParallelDef2.setText("Use parallel jobs :"); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalIndent = 15; + internalBuilderParallelDef2.setLayoutData(gd); + + internalBuilderParallelDef2.addSelectionListener(new SelectionAdapter () { + public void widgetSelected(SelectionEvent e) { + Configuration config = (Configuration)BuildSettingsBlock.this.parent.getSelectedConfigurationClone(); + config.setParallelDef(!internalBuilderParallelDef2.getSelection()); + setValues(); + setDirty(true); + } + }); + + internalBuilderParallelDef2.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent event) { internalBuilderParallelDef2 = null; } + }); + + parallelProcesses = new Spinner(internalBuilderGroup, SWT.BORDER); + parallelProcesses.setFont(internalBuilderGroup.getFont()); + parallelProcesses.setBackground(internalBuilderGroup.getBackground()); + parallelProcesses.setForeground(internalBuilderGroup.getForeground()); + parallelProcesses.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + parallelProcesses.setValues(cpuNumber, 1, 10000, 0, 1, 10); + parallelProcesses.setToolTipText(ManagedBuilderUIMessages.getResourceString(INTERNAL_BUILDER_PARALLEL_TOOLTIP)); + + parallelProcesses.addSelectionListener(new SelectionAdapter () { + public void widgetSelected(SelectionEvent e) { + Configuration config = (Configuration)BuildSettingsBlock.this.parent.getSelectedConfigurationClone(); + config.setParallelNumber(parallelProcesses.getSelection()); + setValues(); + setDirty(true); + } + }); + + parallelProcesses.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent event) { parallelProcesses = null; } + }); } + private Button createInternalBuilderButton(String s, int hSpan) { + Button b = new Button(internalBuilderGroup, SWT.CHECK | SWT.LEFT); + b.setFont(internalBuilderGroup.getFont()); + b.setText(s); + b.setBackground(internalBuilderGroup.getBackground()); + b.setForeground(internalBuilderGroup.getForeground()); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = hSpan; + b.setLayoutData(gd); + return b; + } + protected void initializeValues() { setValues(); setDirty(false); @@ -380,6 +488,10 @@ public class BuildSettingsBlock extends AbstractCOptionPage { boolean internalBuilderOn = config.isInternalBuilderEnabled(); internalBuilderEnable.setSelection(internalBuilderOn); internalBuilderIgnoreErr.setSelection(config.getInternalBuilderIgnoreErr()); + internalBuilderParallel.setSelection(config.getInternalBuilderParallel()); + internalBuilderParallelDef1.setSelection(config.getParallelDef()); + internalBuilderParallelDef2.setSelection(!config.getParallelDef()); + parallelProcesses.setSelection(config.getParallelNumber()); makeCommandDefault.setEnabled(!internalBuilderOn); makeCommandEntry.setEnabled(!internalBuilderOn); @@ -387,6 +499,10 @@ public class BuildSettingsBlock extends AbstractCOptionPage { buildMacrosExpand.setEnabled(!internalBuilderOn); buildMacrosExpandGroup.setEnabled(!internalBuilderOn); internalBuilderIgnoreErr.setEnabled(internalBuilderOn); + internalBuilderParallel.setEnabled(internalBuilderOn); + internalBuilderParallelDef1.setEnabled(internalBuilderOn && config.getInternalBuilderParallel()); + internalBuilderParallelDef2.setEnabled(internalBuilderOn && config.getInternalBuilderParallel()); + parallelProcesses.setEnabled(internalBuilderOn && config.getInternalBuilderParallel() && !config.getParallelDef()); // setDirty(false); } @@ -456,6 +572,9 @@ public class BuildSettingsBlock extends AbstractCOptionPage { selectedConfiguration.enableInternalBuilder(cloneConfig.isInternalBuilderEnabled()); selectedConfiguration.setInternalBuilderIgnoreErr(cloneConfig.getInternalBuilderIgnoreErr()); + selectedConfiguration.setInternalBuilderParallel(cloneConfig.getInternalBuilderParallel()); + selectedConfiguration.setParallelDef(cloneConfig.getParallelDef()); + selectedConfiguration.setParallelNumber(cloneConfig.getParallelNumber()); setDirty(false); } diff --git a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/PluginResources.properties b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/PluginResources.properties index b51a7288d9b..d3cef4a727f 100644 --- a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/PluginResources.properties +++ b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/PluginResources.properties @@ -113,7 +113,11 @@ BuildSettingsBlock.label.internal.builder.group=Internal Builder BuildSettingsBlock.label.internal.builder.enable=Enable Internal Builder BuildSettingsBlock.label.internal.builder.ignore.err=Ignore build errors BuildSettingsBlock.label.internal.builder.experimental.note=NOTE: This is experimental functionality - +BuildSettingsBlock.label.internal.builder.parallel.head=Parallel build +BuildSettingsBlock.label.internal.builder.parallel.use=Enable parallel build +BuildSettingsBlock.label.internal.builder.parallel.default=Use optimal jobs number +BuildSettingsBlock.label.internal.builder.parallel.number=Use parallel jobs: +BuildSettingsBlock.label.internal.builder.parallel.tooltip=Select number of jobs really used for build # ----------- Build Steps Block ----------- BuildStepSettingsBlock.label.Settings=Build Steps @@ -234,6 +238,15 @@ ResourceBuildPropertyPage.config.notselected=No configurations selected ResourceBuildPropertyPage.rc.non.build=Managed Build settings for this resource are not available ResourceBuildPropertyPage.rc.generated=The selected resource is created by the buildfile generator +# ----------- Languages Page + +CLanguagesPropertyPage.label.ActiveResource=Active Resource configuration +CLanguagesPropertyPage.label.ResourceSettings=Known languages +CLanguagesPropertyPage.label.ApplyToAllCheckBox=Apply changes to all configurations +CLanguagesPropertyPage.label.Configuration=Configuration: +CLanguagesPropertyPage.tip.applytoallcheck=Apply changes to all funcking configurations + + # ----------- Resource Custom Build Step Block ----------- ResourceCustomBuildStepBlock.label.settings=Custom Build Steps ResourceCustomBuildStepBlock.label.tool.group=Resource Custom Build Step