1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-19 14:15:50 +02:00

Backport implementation of bug 259768: "Use optimal jobs number:

highly misleading" from 8.1 to 8.0.

Change-Id: I5a3d33b21b306b30411dc6eb2325d77d0383c9bf
Reviewed-on: https://git.eclipse.org/r/9731
Reviewed-by: Doug Schaefer <dschaefer@qnx.com>
IP-Clean: Doug Schaefer <dschaefer@qnx.com>
Tested-by: Doug Schaefer <dschaefer@qnx.com>
This commit is contained in:
Marc Gobeil 2013-01-16 18:04:19 -05:00 committed by Doug Schaefer
parent f0f4c6e022
commit 05cfb020bb
15 changed files with 891 additions and 681 deletions

View file

@ -1757,8 +1757,27 @@ If this attribute is not specified, MBS will assume that there are no reserved m
<attribute name="parallelBuildCmd" type="string"> <attribute name="parallelBuildCmd" type="string">
<annotation> <annotation>
<documentation> <documentation>
specifies the &quot;parallel build&quot; builder option. Specifies the command for &quot;parallel build&quot;.
If the builder supports specifying custom number of parallel jobs, the option definition may contain &quot;*&quot; the Build System sill substitute the &quot;*&quot; with the number of parallel threads to be used. If the builder supports specifying custom number of parallel jobs the option definition may contain &quot;*&quot;. The Build System will substitute the &quot;*&quot; with the number of parallel threads to be used. In case of &quot;unlimited&quot; jobs jobs number will be omitted.
For example, builder representing GNU make would define parallelBuildCmd as &quot;-j*&quot;.
</documentation>
</annotation>
</attribute>
<attribute name="parallelBuildOn" type="boolean">
<annotation>
<documentation>
Defines if the parallel build is enabled in newly created project by default (when parallel build is supported). The number of jobs is defined by &quot;parallelizationNumber&quot; attribute. If &quot;parallelizationNumber&quot; is not defined &quot;optimal&quot; value will be used.
</documentation>
</annotation>
</attribute>
<attribute name="parallelizationNumber" type="string">
<annotation>
<documentation>
Sets maximum number of parallel threads/jobs to be used by builder (that value can be changed after creation of project by user).
A positive number or value &quot;optimal&quot; or &quot;unlimited&quot; are recognized:
- number 1 will cause parallel build to be turned off,
- &quot;optimal&quot; will set maximum number of jobs to number of processors on the system,
- &quot;unlimited&quot; will make builder to run as many threads/jobs as possible.
</documentation> </documentation>
</annotation> </annotation>
</attribute> </attribute>

View file

@ -76,13 +76,16 @@ public interface IBuilder extends IHoldsOptions, IMakeBuilderInfo {
static final String ATTRIBUTE_CUSTOMIZED_ERROR_PARSERS = "customizedErrorParsers"; //$NON-NLS-1$ static final String ATTRIBUTE_CUSTOMIZED_ERROR_PARSERS = "customizedErrorParsers"; //$NON-NLS-1$
static final String ATTRIBUTE_CUSTOM_PROPS = "customBuilderProperties"; //$NON-NLS-1$ static final String ATTRIBUTE_CUSTOM_PROPS = "customBuilderProperties"; //$NON-NLS-1$
// static final String ATTRIBUTE_CUSTOMIZED_ERROR_PARSERS = "customizedErrorParsers"; //$NON-NLS-1$
static final String ATTRIBUTE_IGNORE_ERR_CMD = "ignoreErrCmd"; //$NON-NLS-1$ static final String ATTRIBUTE_IGNORE_ERR_CMD = "ignoreErrCmd"; //$NON-NLS-1$
static final String ATTRIBUTE_STOP_ON_ERR = "stopOnErr"; //$NON-NLS-1$ static final String ATTRIBUTE_STOP_ON_ERR = "stopOnErr"; //$NON-NLS-1$
static final String ATTRIBUTE_PARALLEL_BUILD_CMD = "parallelBuildCmd"; //$NON-NLS-1$ static final String ATTRIBUTE_PARALLEL_BUILD_CMD = "parallelBuildCmd"; //$NON-NLS-1$
static final String ATTRIBUTE_PARALLELIZATION_NUMBER = "parallelizationNumber"; //$NON-NLS-1$
static final String ATTRIBUTE_PARALLEL_BUILD_ON = "parallelBuildOn"; //$NON-NLS-1$ static final String ATTRIBUTE_PARALLEL_BUILD_ON = "parallelBuildOn"; //$NON-NLS-1$
static final String ATTRIBUTE_PARALLELIZATION_NUMBER = "parallelizationNumber"; //$NON-NLS-1$
/** @since 8.0 */
static final String VALUE_OPTIMAL = "optimal"; //$NON-NLS-1$
/** @since 8.0 */
static final String VALUE_UNLIMITED = "unlimited"; //$NON-NLS-1$
static final String PARALLEL_PATTERN_NUM = "*"; //$NON-NLS-1$ static final String PARALLEL_PATTERN_NUM = "*"; //$NON-NLS-1$
static final String PARALLEL_PATTERN_NUM_START = "["; //$NON-NLS-1$ static final String PARALLEL_PATTERN_NUM_START = "["; //$NON-NLS-1$
static final String PARALLEL_PATTERN_NUM_END = "]"; //$NON-NLS-1$ static final String PARALLEL_PATTERN_NUM_END = "]"; //$NON-NLS-1$
@ -92,15 +95,9 @@ public interface IBuilder extends IHoldsOptions, IMakeBuilderInfo {
static final String DEFAULT_TARGET_INCREMENTAL = "all"; //$NON-NLS-1$ static final String DEFAULT_TARGET_INCREMENTAL = "all"; //$NON-NLS-1$
static final String DEFAULT_TARGET_CLEAN = "clean"; //$NON-NLS-1$ static final String DEFAULT_TARGET_CLEAN = "clean"; //$NON-NLS-1$
static final String DEFAULT_TARGET_AUTO = "all"; //$NON-NLS-1$ static final String DEFAULT_TARGET_AUTO = "all"; //$NON-NLS-1$
/** @since 6.0 */
/**
* @since 6.0
*/
static final String ATTRIBUTE_COMMAND_LAUNCHER = "commandLauncher"; //$NON-NLS-1$ static final String ATTRIBUTE_COMMAND_LAUNCHER = "commandLauncher"; //$NON-NLS-1$
/** @since 8.0 */
/**
* @since 8.0
*/
static final String ATTRIBUTE_BUILD_RUNNER = "buildRunner"; //$NON-NLS-1$ static final String ATTRIBUTE_BUILD_RUNNER = "buildRunner"; //$NON-NLS-1$
/** /**

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2007, 2010 Intel Corporation and others. * Copyright (c) 2007, 2011 Intel Corporation and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -13,19 +13,56 @@ package org.eclipse.cdt.managedbuilder.core;
import org.eclipse.cdt.core.settings.model.ICMultiItemsHolder; import org.eclipse.cdt.core.settings.model.ICMultiItemsHolder;
import org.eclipse.cdt.managedbuilder.buildproperties.IBuildProperty; import org.eclipse.cdt.managedbuilder.buildproperties.IBuildProperty;
import org.eclipse.cdt.managedbuilder.buildproperties.IBuildPropertyValue; import org.eclipse.cdt.managedbuilder.buildproperties.IBuildPropertyValue;
import org.eclipse.cdt.managedbuilder.internal.core.Builder;
/** /**
* This class is to combine multiple configurations to one to support
* selection of multiple configurations on property pages.
*
* @noextend This class is not intended to be subclassed by clients. * @noextend This class is not intended to be subclassed by clients.
* @noimplement This interface is not intended to be implemented by clients. * @noimplement This interface is not intended to be implemented by clients.
*/ */
public interface IMultiConfiguration extends IConfiguration, ICMultiItemsHolder { public interface IMultiConfiguration extends IConfiguration, ICMultiItemsHolder {
/**
* Check if all configurations' builders are operating in parallel mode.
* @return {@code true} if parallel mode is enabled for all configurations,
* {@code false} otherwise.
*/
boolean getParallelDef(); boolean getParallelDef();
void setParallelDef(boolean def); /**
* Set same parallel execution mode for all configurations' builders.
* @see Builder#setParallelBuildOn(boolean)
*
* @param parallel - the flag to enable or disable parallel mode.
*/
void setParallelDef(boolean parallel);
/**
* Returns maximum number of parallel threads/jobs used by the configurations' builders.
* @see #setParallelDef(boolean)
*
* @return - maximum number of parallel threads or jobs used by each builder or 0 if the numbers
* don't match.
*/
int getParallelNumber(); int getParallelNumber();
void setParallelNumber(int num);
/**
* Sets maximum number of parallel threads/jobs to be used by each builder.
*
* @param jobs - maximum number of jobs or threads, see for more details
* {@link Builder#getOptimalParallelJobNum()}.
*/
void setParallelNumber(int jobs);
/**
* Check if all configurations' internal builders are operating in parallel mode.
* @return {@code true} if parallel mode is enabled for all configurations,
* {@code false} otherwise.
*
* @deprecated since CDT 9.0. Use {@link #getParallelDef()}
*/
@Deprecated
boolean getInternalBuilderParallel(); boolean getInternalBuilderParallel();
boolean isInternalBuilderEnabled(); boolean isInternalBuilderEnabled();

View file

@ -65,7 +65,7 @@ public class InternalBuildRunner extends AbstractBuildRunner {
public boolean invokeBuild(int kind, IProject project, IConfiguration configuration, public boolean invokeBuild(int kind, IProject project, IConfiguration configuration,
IBuilder builder, IConsole console, IMarkerGenerator markerGenerator, IBuilder builder, IConsole console, IMarkerGenerator markerGenerator,
IncrementalProjectBuilder projectBuilder, IProgressMonitor monitor) throws CoreException { IncrementalProjectBuilder projectBuilder, IProgressMonitor monitor) throws CoreException {
boolean isParallel = builder.isParallelBuildOn() && builder.getParallelizationNum() > 1; boolean isParallel = builder.getParallelizationNum() > 1;
// boolean buildIncrementaly = true; // boolean buildIncrementaly = true;
boolean resumeOnErr = !builder.isStopOnError(); boolean resumeOnErr = !builder.isStopOnError();
@ -173,8 +173,7 @@ public class InternalBuildRunner extends AbstractBuildRunner {
break; break;
case IBuildModelBuilder.STATUS_ERROR_LAUNCH: case IBuildModelBuilder.STATUS_ERROR_LAUNCH:
default: default:
buf.append(ManagedMakeMessages buf.append(ManagedMakeMessages.getResourceString(BUILD_FAILED_ERR));
.getResourceString(BUILD_FAILED_ERR));
break; break;
} }
buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$//$NON-NLS-2$ buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$//$NON-NLS-2$
@ -194,8 +193,7 @@ public class InternalBuildRunner extends AbstractBuildRunner {
epmOutputStream.close(); epmOutputStream.close();
epmOutputStream = null; epmOutputStream = null;
// Generate any error markers that the build has discovered // Generate any error markers that the build has discovered
monitor.subTask(ManagedMakeMessages monitor.subTask(ManagedMakeMessages.getResourceString(MARKERS));
.getResourceString(MARKERS));
bsMngr.setProjectBuildState(project, pBS); bsMngr.setProjectBuildState(project, pBS);
} else { } else {

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2006, 2007 Intel Corporation and others. * Copyright (c) 2006, 2011 Intel Corporation and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -11,42 +11,28 @@
package org.eclipse.cdt.managedbuilder.internal.buildmodel; package org.eclipse.cdt.managedbuilder.internal.buildmodel;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.Vector;
import org.eclipse.cdt.managedbuilder.buildmodel.IBuildCommand; import org.eclipse.cdt.managedbuilder.buildmodel.IBuildCommand;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.cdt.managedbuilder.envvar.IBuildEnvironmentVariable;
import org.eclipse.cdt.managedbuilder.envvar.IEnvironmentVariableProvider;
import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IProgressMonitor;
/** /**
* This class implements process pool management for internal builder * 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 { public class BuildProcessManager {
protected OutputStream out; protected OutputStream out;
protected OutputStream err; protected OutputStream err;
protected boolean show; protected boolean show;
protected ProcessLauncher[] processes; protected Vector<ProcessLauncher> processes;
protected int maxProcesses; 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 * Initializes process manager
* *
@ -59,7 +45,7 @@ public class BuildProcessManager {
err = _err; err = _err;
show = _show; show = _show;
maxProcesses = _procNumber; maxProcesses = _procNumber;
processes = new ProcessLauncher[maxProcesses]; processes = new Vector<ProcessLauncher>(Math.min(10, maxProcesses), 10);
} }
/** /**
@ -79,18 +65,19 @@ public class BuildProcessManager {
* @param monitor Progress monitor for this task * @param monitor Progress monitor for this task
*/ */
public ProcessLauncher launchProcess(IBuildCommand cmd, IPath cwd, IProgressMonitor monitor) { public ProcessLauncher launchProcess(IBuildCommand cmd, IPath cwd, IProgressMonitor monitor) {
if (hasEmpty()) { for (int i = 0; i < maxProcesses; i++) {
int i = 0; if (i >= processes.size()) {
for (; i < maxProcesses; i++) { ProcessLauncher process = new ProcessLauncher(cmd.getCommand(), cmd.getArgs(), mapToStringArray(cmd.getEnvironment()), cwd, out, err, monitor, show);
if (processes[i] == null || processes[i].queryState() == ProcessLauncher.STATE_DONE) { processes.add(process);
break; process.launch();
} return process;
}
if (i < maxProcesses) { }
processes[i] = new ProcessLauncher(cmd.getCommand(), cmd.getArgs(), mapToStringArray(cmd.getEnvironment()), cwd, out, err, monitor, show); if (processes.get(i).queryState() == ProcessLauncher.STATE_DONE) {
processes[i].launch(); ProcessLauncher process = new ProcessLauncher(cmd.getCommand(), cmd.getArgs(), mapToStringArray(cmd.getEnvironment()), cwd, out, err, monitor, show);
return processes[i]; processes.set(i, process);
process.launch();
return process;
} }
} }
return null; return null;
@ -102,36 +89,37 @@ public class BuildProcessManager {
* returned as a result. Otherwise this method returns null. * returned as a result. Otherwise this method returns null.
*/ */
public ProcessLauncher queryStates() { public ProcessLauncher queryStates() {
ProcessLauncher result = null; for (ProcessLauncher process : processes) {
int state = process.queryState();
for (int i = 0; i < maxProcesses; i++) { if (state != ProcessLauncher.STATE_RUNNING && state != ProcessLauncher.STATE_DONE)
if (processes[i] != null) { return process;
int state = processes[i].queryState();
if (state != ProcessLauncher.STATE_RUNNING) {
if (state != ProcessLauncher.STATE_DONE && result == null)
result = processes[i];
}
}
} }
return result; return null;
} }
/** /**
* Checks states of all currently running processes. * Checks states of all currently running processes.
*/ */
public boolean hasEmpty() { public boolean hasEmpty() {
for (int i = 0; i < maxProcesses; i++) { if (processes.size() < maxProcesses)
if (processes[i] == null)
return true; return true;
else {
if (processes[i].queryState() != ProcessLauncher.STATE_RUNNING) for (ProcessLauncher process : processes) {
if (process.queryState() != ProcessLauncher.STATE_RUNNING)
return true; return true;
} }
}
return false; return false;
} }
/**
* Returns maximum threads used up to that point
*/
public int getThreadsUsed() {
return processes.size();
}
/** /**
* Converts map to strings array * Converts map to strings array
@ -152,40 +140,10 @@ public class BuildProcessManager {
/** /**
* @return Number of processors detected * @return Number of processors detected
* @deprecated since CDT 9.0 - just use Runtime.getRuntime().availableProcessors()
*/ */
@Deprecated
static public int checkCPUNumber() { static public int checkCPUNumber() {
if (procNumber > 0) return procNumber; return Runtime.getRuntime().availableProcessors();
procNumber = 1;
int x = 0;
String os = System.getProperty("os.name"); //$NON-NLS-1$
if (os != null) {
if (os.startsWith("Win")) { //$NON-NLS-1$
IEnvironmentVariableProvider evp = ManagedBuildManager.getEnvironmentVariableProvider();
if (evp != null) {
IBuildEnvironmentVariable var = evp.getVariable("NUMBER_OF_PROCESSORS", null, false, false); //$NON-NLS-1$
if (var != null) {
try {
x = new Integer(var.getValue()).intValue();
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;
} }
} }

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2006 Intel Corporation and others. * Copyright (c) 2006, 2011 Intel Corporation and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -17,6 +17,7 @@ import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.Vector;
import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.managedbuilder.buildmodel.IBuildCommand; import org.eclipse.cdt.managedbuilder.buildmodel.IBuildCommand;
@ -205,18 +206,16 @@ public class ParallelBuilder {
if(cwd == null) cwd = des.getDefaultBuildDirLocation(); if(cwd == null) cwd = des.getDefaultBuildDirLocation();
int threads = 1; int threads = 1;
if (cfg instanceof Configuration) { if (cfg instanceof Configuration) {
if (((Configuration)cfg).getParallelDef())
threads = BuildProcessManager.checkCPUNumber();
else
threads = ((Configuration)cfg).getParallelNumber(); threads = ((Configuration)cfg).getParallelNumber();
} }
ParallelBuilder builder = new ParallelBuilder(cwd, dirs, out, err, monitor, resumeOnErrors, buildIncrementally); ParallelBuilder builder = new ParallelBuilder(cwd, dirs, out, err, monitor, resumeOnErrors, buildIncrementally);
builder.enqueueAll(des); builder.enqueueAll(des);
builder.sortQueue(); builder.sortQueue();
monitor.beginTask("", builder.queue.size()); //$NON-NLS-1$ monitor.beginTask("", builder.queue.size()); //$NON-NLS-1$
builder.dispatch(new BuildProcessManager(out, err, true, threads)); BuildProcessManager buildProcessManager = new BuildProcessManager(out, err, true, threads);
builder.dispatch(buildProcessManager);
lastThreadsUsed = buildProcessManager.getThreadsUsed();
monitor.done(); monitor.done();
lastThreadsUsed = threads;
return IBuildModelBuilder.STATUS_OK; return IBuildModelBuilder.STATUS_OK;
} }
@ -295,10 +294,8 @@ public class ParallelBuilder {
* Dispatches the build queue and returns build status * Dispatches the build queue and returns build status
*/ */
protected int dispatch(BuildProcessManager mgr) { protected int dispatch(BuildProcessManager mgr) {
ActiveBuildStep[] active = new ActiveBuildStep[mgr.getMaxProcesses()]; int maxProcesses = mgr.getMaxProcesses();
for (int i = 0; i < active.length; i++) { Vector<ActiveBuildStep> active = new Vector<ActiveBuildStep>(Math.min(maxProcesses, 10), 10);
active[i] = null; // new ActiveBuildStep();
}
int activeCount = 0; int activeCount = 0;
int maxLevel = 0; int maxLevel = 0;
@ -332,9 +329,8 @@ public class ParallelBuilder {
proceed = false; proceed = false;
} else { } else {
// Check "active steps" list for completed ones // Check "active steps" list for completed ones
for (int i = 0; i < active.length; i++) { for (ActiveBuildStep buildStep : active) {
if (active[i] == null) continue; ProcessLauncher pl = buildStep.getLauncher();
ProcessLauncher pl = active[i].getLauncher();
if (pl == null) continue; if (pl == null) continue;
if (pl.queryState() == ProcessLauncher.STATE_DONE) { if (pl.queryState() == ProcessLauncher.STATE_DONE) {
// If process has terminated with error, break loop // If process has terminated with error, break loop
@ -345,8 +341,8 @@ public class ParallelBuilder {
break main_loop; break main_loop;
} }
// Try to launch next command for the current active step // Try to launch next command for the current active step
if (active[i].isDone()) continue; if (buildStep.isDone()) continue;
if (active[i].launchNextCmd(mgr)) { if (buildStep.launchNextCmd(mgr)) {
// Command has been launched. Check if process pool is not maximized yet // Command has been launched. Check if process pool is not maximized yet
if (!mgr.hasEmpty()) { if (!mgr.hasEmpty()) {
proceed = false; proceed = false;
@ -354,7 +350,7 @@ public class ParallelBuilder {
} }
} else { } else {
// Command has not been launched: step complete // Command has not been launched: step complete
refreshOutputs(active[i].getStep()); refreshOutputs(buildStep.getStep());
activeCount--; activeCount--;
monitor.worked(1); monitor.worked(1);
} }
@ -373,7 +369,7 @@ public class ParallelBuilder {
} }
// Check if we need to schedule another process // Check if we need to schedule another process
if (queue.size() != 0 && activeCount < active.length) { if (queue.size() != 0 && activeCount < maxProcesses) {
// Need to schedule another process // Need to schedule another process
Iterator<BuildQueueElement> iter = queue.iterator(); Iterator<BuildQueueElement> iter = queue.iterator();
@ -381,8 +377,8 @@ public class ParallelBuilder {
while (iter.hasNext()) { while (iter.hasNext()) {
BuildQueueElement elem = iter.next(); BuildQueueElement elem = iter.next();
// If "active steps" list is full, then break loop // If "active steps" list reaches maximum, then break loop
if (activeCount == active.length) if (activeCount == maxProcesses)
break; break;
// If current element's level exceeds maximum level of currently built // If current element's level exceeds maximum level of currently built
@ -391,14 +387,13 @@ public class ParallelBuilder {
break; break;
//Check if all prerequisites are built //Check if all prerequisites are built
IBuildResource[] res = elem.getStep().getInputResources();
boolean prereqBuilt = true; boolean prereqBuilt = true;
for (int j = 0; j < res.length; j++) { for (IBuildResource bldRes : elem.getStep().getInputResources()) {
IBuildStep stp = res[j].getProducerStep(); // step which produces input for curr IBuildStep step = bldRes.getProducerStep(); // step which produces input for curr
boolean built = true; boolean built = true;
if (stp != stp.getBuildDescription().getInputStep()) { if (step != step.getBuildDescription().getInputStep()) {
for (int k = 0; k < active.length; k++) { for (ActiveBuildStep buildStep : active) {
if (active[k] != null && active[k].getStep().equals(stp) && !active[k].isDone()) { if (buildStep != null && buildStep.getStep().equals(step) && !buildStep.isDone()) {
built = false; built = false;
break; break;
} }
@ -417,10 +412,21 @@ public class ParallelBuilder {
// Remove element from the build queue and add it to the // Remove element from the build queue and add it to the
// "active steps" list. // "active steps" list.
iter.remove(); iter.remove();
for (int i = 0; i < active.length; i++) { for (int i = 0; i < maxProcesses; i++) {
if (active[i] == null || active[i].isDone()) { if (i >= active.size()) {
active[i] = new ActiveBuildStep(step); // add new item
if (active[i].launchNextCmd(mgr)) activeCount++; ActiveBuildStep buildStep = new ActiveBuildStep(step);
active.add(buildStep);
if (buildStep.launchNextCmd(mgr))
activeCount++;
break;
}
if (active.get(i).isDone()) {
// replace old item
ActiveBuildStep buildStep = new ActiveBuildStep(step);
active.set(i, buildStep);
if (buildStep.launchNextCmd(mgr))
activeCount++;
break; break;
} }
} }

View file

@ -40,10 +40,10 @@ import org.eclipse.cdt.core.settings.model.extension.CBuildData;
import org.eclipse.cdt.core.settings.model.util.CDataUtil; import org.eclipse.cdt.core.settings.model.util.CDataUtil;
import org.eclipse.cdt.core.settings.model.util.LanguageSettingEntriesSerializer; import org.eclipse.cdt.core.settings.model.util.LanguageSettingEntriesSerializer;
import org.eclipse.cdt.internal.core.SafeStringInterner; import org.eclipse.cdt.internal.core.SafeStringInterner;
import org.eclipse.cdt.managedbuilder.core.AbstractBuildRunner;
import org.eclipse.cdt.managedbuilder.core.BuildException; import org.eclipse.cdt.managedbuilder.core.BuildException;
import org.eclipse.cdt.managedbuilder.core.ExternalBuildRunner; import org.eclipse.cdt.managedbuilder.core.ExternalBuildRunner;
import org.eclipse.cdt.managedbuilder.core.IBuildObject; import org.eclipse.cdt.managedbuilder.core.IBuildObject;
import org.eclipse.cdt.managedbuilder.core.AbstractBuildRunner;
import org.eclipse.cdt.managedbuilder.core.IBuilder; import org.eclipse.cdt.managedbuilder.core.IBuilder;
import org.eclipse.cdt.managedbuilder.core.IConfiguration; import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.IManagedConfigElement; import org.eclipse.cdt.managedbuilder.core.IManagedConfigElement;
@ -66,6 +66,7 @@ import org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator2;
import org.eclipse.cdt.managedbuilder.makegen.gnu.GnuMakefileGenerator; import org.eclipse.cdt.managedbuilder.makegen.gnu.GnuMakefileGenerator;
import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IncrementalProjectBuilder; import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IExtension;
@ -79,7 +80,7 @@ import org.eclipse.core.variables.VariablesPlugin;
import org.osgi.framework.Version; import org.osgi.framework.Version;
public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider<Builder>, IRealBuildObjectAssociation { public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider<Builder>, IRealBuildObjectAssociation {
public static final int UNLIMITED_JOBS = Integer.MAX_VALUE;
private static final String EMPTY_STRING = ""; //$NON-NLS-1$ private static final String EMPTY_STRING = ""; //$NON-NLS-1$
// Superclass // Superclass
@ -119,10 +120,12 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider
private HashMap<String, String> customBuildProperties; private HashMap<String, String> customBuildProperties;
// private Boolean isWorkspaceBuildPath; // private Boolean isWorkspaceBuildPath;
private String ignoreErrCmd; private String ignoreErrCmd;
private String parallelBuildCmd;
private Boolean stopOnErr; private Boolean stopOnErr;
private Integer parallelNum; // parallelization
private Boolean parallelBuildOn; private String parallelBuildCmd;
private Boolean isParallelBuildEnabled;
private Integer parallelNumberAttribute; // negative number denotes "optimal" value, see getOptimalParallelJobNum()
private boolean isTest; private boolean isTest;
// Miscellaneous // Miscellaneous
@ -327,9 +330,10 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider
stopOnErr = builder.stopOnErr; stopOnErr = builder.stopOnErr;
ignoreErrCmd = builder.ignoreErrCmd; ignoreErrCmd = builder.ignoreErrCmd;
isParallelBuildEnabled = builder.isParallelBuildEnabled;
parallelNumberAttribute = builder.parallelNumberAttribute;
parallelBuildCmd = builder.parallelBuildCmd; parallelBuildCmd = builder.parallelBuildCmd;
parallelNum = builder.parallelNum;
parallelBuildOn = builder.parallelBuildOn;
if(builder.outputEntries != null){ if(builder.outputEntries != null){
outputEntries = builder.outputEntries.clone(); outputEntries = builder.outputEntries.clone();
@ -372,17 +376,15 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider
} catch (CoreException e) { } catch (CoreException e) {
} }
} }
if(getParallelizationNum() != builder.getParallelizationNum() if (isParallelBuildOn() != builder.isParallelBuildOn() && supportsParallelBuild()) {
&& supportsParallelBuild()){
try { try {
setParallelizationNum(builder.getParallelizationNum()); setParallelBuildOn(builder.isParallelBuildOn());
} catch (CoreException e) { } catch (CoreException e) {
} }
} }
if(isParallelBuildOn() != builder.isParallelBuildOn() if (getParallelizationNumAttribute() != builder.getParallelizationNumAttribute() && supportsParallelBuild()) {
&& supportsParallelBuild()){
try { try {
setParallelBuildOn(builder.isParallelBuildOn()); setParallelizationNum(builder.getParallelizationNumAttribute());
} catch (CoreException e) { } catch (CoreException e) {
} }
} }
@ -556,18 +558,18 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider
if (tmp != null) if (tmp != null)
stopOnErr = Boolean.valueOf(tmp); stopOnErr = Boolean.valueOf(tmp);
parallelBuildCmd = SafeStringInterner.safeIntern(element.getAttribute(ATTRIBUTE_PARALLEL_BUILD_CMD)); tmp = element.getAttribute(ATTRIBUTE_PARALLEL_BUILD_CMD);
tmp = element.getAttribute(ATTRIBUTE_PARALLELIZATION_NUMBER);
if(tmp != null){
try {
parallelNum = Integer.decode(tmp);
} catch (NumberFormatException e){
}
}
tmp = element.getAttribute(ATTRIBUTE_PARALLEL_BUILD_ON);
if (tmp != null) if (tmp != null)
parallelBuildOn = Boolean.valueOf(tmp); parallelBuildCmd = SafeStringInterner.safeIntern(tmp);
tmp = element.getAttribute(ATTRIBUTE_PARALLEL_BUILD_ON);
if (tmp != null) {
isParallelBuildEnabled = Boolean.valueOf(tmp);
if (isParallelBuildEnabled) {
tmp = element.getAttribute(ATTRIBUTE_PARALLELIZATION_NUMBER);
setParallelizationNumAttribute(decodeParallelizationNumber(element.getAttribute(ATTRIBUTE_PARALLELIZATION_NUMBER)));
}
}
// Get the semicolon separated list of IDs of the error parsers // Get the semicolon separated list of IDs of the error parsers
errorParserIds = SafeStringInterner.safeIntern(element.getAttribute(IToolChain.ERROR_PARSERS)); errorParserIds = SafeStringInterner.safeIntern(element.getAttribute(IToolChain.ERROR_PARSERS));
@ -618,6 +620,43 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider
fBuildRunnerElement = ((DefaultManagedConfigElement)element).getConfigurationElement(); fBuildRunnerElement = ((DefaultManagedConfigElement)element).getConfigurationElement();
} }
private String encodeParallelizationNumber(Integer jobsNumber) {
if (jobsNumber <= 0)
return VALUE_OPTIMAL;
if (jobsNumber.equals(UNLIMITED_JOBS))
return VALUE_UNLIMITED;
return jobsNumber.toString();
}
private int decodeParallelizationNumber(String value) {
int parallelNumber = -1;
if (VALUE_OPTIMAL.equals(value)) {
parallelNumber = -getOptimalParallelJobNum();
} else if (VALUE_UNLIMITED.equals(value)) {
parallelNumber = UNLIMITED_JOBS;
} else {
try {
parallelNumber = Integer.decode(value);
} catch (NumberFormatException e) {
ManagedBuilderCorePlugin.log(e);
parallelNumber = getOptimalParallelJobNum();
}
if (parallelNumber <= 0) {
// compatibility with legacy representation - it was that inconsistent
if (isInternalBuilder()) {
// "optimal" for Internal Builder
parallelNumber = -getOptimalParallelJobNum();
} else {
// unlimited for External Builder
parallelNumber = UNLIMITED_JOBS;
}
}
}
return parallelNumber;
}
/** /**
* Initialize the builder information from the XML element * Initialize the builder information from the XML element
* specified in the argument * specified in the argument
@ -752,20 +791,18 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider
if (tmp != null) if (tmp != null)
stopOnErr = Boolean.valueOf(tmp); stopOnErr = Boolean.valueOf(tmp);
if(element.getAttribute(ATTRIBUTE_PARALLEL_BUILD_CMD) != null) tmp = element.getAttribute(ATTRIBUTE_PARALLEL_BUILD_CMD);
parallelBuildCmd = SafeStringInterner.safeIntern(element.getAttribute(ATTRIBUTE_PARALLEL_BUILD_CMD)); if (tmp != null)
parallelBuildCmd = SafeStringInterner.safeIntern(tmp);
tmp = element.getAttribute(ATTRIBUTE_PARALLELIZATION_NUMBER);
if(tmp != null){
try {
parallelNum = Integer.decode(tmp);
} catch (NumberFormatException e){
}
}
tmp = element.getAttribute(ATTRIBUTE_PARALLEL_BUILD_ON); tmp = element.getAttribute(ATTRIBUTE_PARALLEL_BUILD_ON);
if(tmp != null) if (tmp != null) {
parallelBuildOn = Boolean.valueOf(tmp); isParallelBuildEnabled = Boolean.valueOf(tmp);
if (isParallelBuildEnabled) {
tmp = element.getAttribute(ATTRIBUTE_PARALLELIZATION_NUMBER);
setParallelizationNumAttribute(decodeParallelizationNumber(element.getAttribute(ATTRIBUTE_PARALLELIZATION_NUMBER)));
}
}
ICStorageElement[] children = element.getChildren(); ICStorageElement[] children = element.getChildren();
for(int i = 0; i < children.length; i++){ for(int i = 0; i < children.length; i++){
@ -873,12 +910,15 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider
element.setAttribute(ATTRIBUTE_IGNORE_ERR_CMD, ignoreErrCmd); element.setAttribute(ATTRIBUTE_IGNORE_ERR_CMD, ignoreErrCmd);
if (stopOnErr != null) if (stopOnErr != null)
element.setAttribute(ATTRIBUTE_STOP_ON_ERR, stopOnErr.toString()); element.setAttribute(ATTRIBUTE_STOP_ON_ERR, stopOnErr.toString());
if (parallelBuildCmd != null) if (parallelBuildCmd != null)
element.setAttribute(ATTRIBUTE_PARALLEL_BUILD_CMD, parallelBuildCmd); element.setAttribute(ATTRIBUTE_PARALLEL_BUILD_CMD, parallelBuildCmd);
if(parallelNum != null)
element.setAttribute(ATTRIBUTE_PARALLELIZATION_NUMBER, parallelNum.toString()); if (isParallelBuildEnabled != null)
if(parallelBuildOn != null) element.setAttribute(ATTRIBUTE_PARALLEL_BUILD_ON, isParallelBuildEnabled.toString());
element.setAttribute(ATTRIBUTE_PARALLEL_BUILD_ON, parallelBuildOn.toString()); if (isParallelBuildOn() && parallelNumberAttribute != null)
element.setAttribute(ATTRIBUTE_PARALLELIZATION_NUMBER, encodeParallelizationNumber(parallelNumberAttribute));
// Note: build file generator cannot be specified in a project file because // Note: build file generator cannot be specified in a project file because
// an IConfigurationElement is needed to load it! // an IConfigurationElement is needed to load it!
if (buildFileGeneratorElement != null) { if (buildFileGeneratorElement != null) {
@ -968,10 +1008,15 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider
if (getIgnoreErrCmdAttribute() != null) if (getIgnoreErrCmdAttribute() != null)
element.setAttribute(ATTRIBUTE_IGNORE_ERR_CMD, getIgnoreErrCmdAttribute()); element.setAttribute(ATTRIBUTE_IGNORE_ERR_CMD, getIgnoreErrCmdAttribute());
element.setAttribute(ATTRIBUTE_STOP_ON_ERR, Boolean.valueOf(isStopOnError()).toString()); element.setAttribute(ATTRIBUTE_STOP_ON_ERR, Boolean.valueOf(isStopOnError()).toString());
if(getParrallelBuildCmd() != null)
element.setAttribute(ATTRIBUTE_PARALLEL_BUILD_CMD, getParrallelBuildCmd()); if (parallelBuildCmd != null)
element.setAttribute(ATTRIBUTE_PARALLELIZATION_NUMBER, new Integer(getParallelizationNumAttribute()).toString()); element.setAttribute(ATTRIBUTE_PARALLEL_BUILD_CMD, parallelBuildCmd);
element.setAttribute(ATTRIBUTE_PARALLEL_BUILD_ON, Boolean.valueOf(isParallelBuildOn()).toString());
if (isParallelBuildEnabled != null)
element.setAttribute(ATTRIBUTE_PARALLEL_BUILD_ON, isParallelBuildEnabled.toString());
if (isParallelBuildOn() && parallelNumberAttribute != null)
element.setAttribute(ATTRIBUTE_PARALLELIZATION_NUMBER, encodeParallelizationNumber(parallelNumberAttribute));
// Note: build file generator cannot be specified in a project file because // Note: build file generator cannot be specified in a project file because
// an IConfigurationElement is needed to load it! // an IConfigurationElement is needed to load it!
if (buildFileGeneratorElement != null) { if (buildFileGeneratorElement != null) {
@ -1042,16 +1087,17 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider
public String getArguments() { public String getArguments() {
String args = getArgumentsAttribute(); String args = getArgumentsAttribute();
String stopOnErrCmd = getStopOnErrCmd(isStopOnError()); String stopOnErrCmd = getStopOnErrCmd(isStopOnError());
String parallelBuildCmd = isParallelBuildOn() ? getParallelizationCmd(getParallelizationNum()) : EMPTY_STRING; int parallelNum = getParallelizationNum();
String parallelCmd = isParallelBuildOn() ? getParallelizationCmd(parallelNum) : EMPTY_STRING;
String reversedStopOnErrCmd = getStopOnErrCmd(!isStopOnError()); String reversedStopOnErrCmd = getStopOnErrCmd(!isStopOnError());
String reversedParallelBuildCmd = !isParallelBuildOn() ? getParallelizationCmd(getParallelizationNum()) : EMPTY_STRING; String reversedParallelBuildCmd = !isParallelBuildOn() ? getParallelizationCmd(parallelNum) : EMPTY_STRING;
args = removeCmd(args, reversedStopOnErrCmd); args = removeCmd(args, reversedStopOnErrCmd);
args = removeCmd(args, reversedParallelBuildCmd); args = removeCmd(args, reversedParallelBuildCmd);
args = addCmd(args, stopOnErrCmd); args = addCmd(args, stopOnErrCmd);
args = addCmd(args, parallelBuildCmd); args = addCmd(args, parallelCmd);
return args != null ? args.trim() : null; return args != null ? args.trim() : null;
} }
@ -1116,16 +1162,25 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider
public String getParallelizationCmd(int num) { public String getParallelizationCmd(int num) {
String pattern = getParrallelBuildCmd(); String pattern = getParrallelBuildCmd();
if(pattern.length() == 0){ if (pattern.length() == 0 || num == 0) {
return EMPTY_STRING;
}if(num == 0){
return EMPTY_STRING; return EMPTY_STRING;
} }
// "unlimited" number of jobs results in not adding the number to parallelization cmd
return processParallelPattern(pattern, num < 0, num); // that behavior corresponds that of "make" flag "-j".
return processParallelPattern(pattern, num == UNLIMITED_JOBS, num);
} }
/**
* This method turns the supplied pattern to parallelization command
*
* It supports 2 kinds of pattern where "*" is replaced with number of jobs:
* <li>Pattern 1 (supports "<b>-j*</b>"): "text*text" -> "text#text"</li>
* <li>Pattern 2 (supports "<b>-[j*]</b>"): "text[text*text]text" -> "texttext#texttext</li>
* <br>Where # is num or empty if {@code empty} is {@code true})
*/
private String processParallelPattern(String pattern, boolean empty, int num){ private String processParallelPattern(String pattern, boolean empty, int num){
Assert.isTrue(num > 0);
int start = pattern.indexOf(PARALLEL_PATTERN_NUM_START); int start = pattern.indexOf(PARALLEL_PATTERN_NUM_START);
int end = -1; int end = -1;
boolean hasStartChar = false; boolean hasStartChar = false;
@ -1238,10 +1293,10 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider
if(newArgs != null){ if(newArgs != null){
String stopOnErrCmd = getStopOnErrCmd(isStopOnError()); String stopOnErrCmd = getStopOnErrCmd(isStopOnError());
String parallelBuildCmd = isParallelBuildOn() ? getParallelizationCmd(getParallelizationNum()) : EMPTY_STRING; String parallelCmd = isParallelBuildOn() ? getParallelizationCmd(getParallelizationNum()) : EMPTY_STRING;
newArgs = removeCmd(newArgs, stopOnErrCmd); newArgs = removeCmd(newArgs, stopOnErrCmd);
newArgs = removeCmd(newArgs, parallelBuildCmd); newArgs = removeCmd(newArgs, parallelCmd);
} }
setArgumentsAttribute(newArgs); setArgumentsAttribute(newArgs);
} }
@ -1916,7 +1971,6 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider
return attr; return attr;
} }
public String getFullBuildTarget() { public String getFullBuildTarget() {
return getIncrementalBuildTarget(); return getIncrementalBuildTarget();
} }
@ -2385,34 +2439,80 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider
return false; return false;
} }
public int getParallelizationNum() { /**
if(supportsParallelBuild()) * Returns the optimal number of parallel jobs.
return getParallelizationNumAttribute(); * The number is the number of available processors on the machine.
return 1; *
* The function never returns number smaller than 1.
*/
public int getOptimalParallelJobNum() {
return Runtime.getRuntime().availableProcessors();
} }
/**
* Returns the internal representation of maximum number of parallel jobs
* to be used for a build.
* Note that negative number represents "optimal" value.
*
* The value of the number is encoded as follows:
* <pre>
* Status Returns
* No parallel 1
* Optimal -CPU# (negative number of processors)
* Specific >0 (positive number)
* Unlimited Builder.UNLIMITED_JOBS
* </pre>
*/
public int getParallelizationNumAttribute() { public int getParallelizationNumAttribute() {
if(parallelNum == null){ if (!isParallelBuildOn())
return 1;
if(parallelNumberAttribute == null){
if(superClass != null){ if(superClass != null){
return ((Builder)superClass).getParallelizationNumAttribute(); return ((Builder)superClass).getParallelizationNumAttribute();
} }
return 1; return 1;
} }
return parallelNum.intValue(); return parallelNumberAttribute.intValue();
} }
public void setParallelizationNum(int num) throws CoreException { private void setParallelizationNumAttribute(int parallelNumber) {
// if(num == 0 || supportsParallelBuild()){ isParallelBuildEnabled = (parallelNumber != 1);
Integer newParallelNum = new Integer(num); if (parallelNumber > 0) {
parallelNumberAttribute = parallelNumber;
} else {
// "optimal"
parallelNumberAttribute = -getOptimalParallelJobNum();
}
}
public int getParallelizationNum() {
return Math.abs(getParallelizationNumAttribute());
}
/**
* {@inheritDoc}
*
* @param jobs - maximum number of jobs. There are 2 special cases:
* <br>- any number <=0 is interpreted as setting "optimal" property,
* the value of the number itself is ignored in this case
* <br>- value 1 will turn parallel mode off.
*/
public void setParallelizationNum(int jobs) throws CoreException {
if (!supportsParallelBuild())
return;
if (parallelNumberAttribute == null || parallelNumberAttribute != jobs) {
String curCmd = getParallelizationCmd(getParallelizationNum()); String curCmd = getParallelizationCmd(getParallelizationNum());
String args = getArgumentsAttribute(); String args = getArgumentsAttribute();
String updatedArgs = removeCmd(args, curCmd); String updatedArgs = removeCmd(args, curCmd);
if (!updatedArgs.equals(args)) { if (!updatedArgs.equals(args)) {
setArgumentsAttribute(updatedArgs); setArgumentsAttribute(updatedArgs);
} }
parallelNum = newParallelNum;
setParallelizationNumAttribute(jobs);
setDirty(true); setDirty(true);
// } }
} }
public boolean supportsParallelBuild() { public boolean supportsParallelBuild() {
@ -2457,29 +2557,33 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider
} }
public boolean isParallelBuildOn() { public boolean isParallelBuildOn() {
if(parallelBuildOn == null){ if (!supportsParallelBuild()) {
return false;
}
if (isParallelBuildEnabled == null) {
if (superClass != null) { if (superClass != null) {
return getSuperClass().isParallelBuildOn(); return getSuperClass().isParallelBuildOn();
} }
return false; return false;
} }
return parallelBuildOn.booleanValue(); return isParallelBuildEnabled.booleanValue();
} }
/**
* {@inheritDoc}
*
* @param on - the flag to enable or disable parallel mode.
* <br>{@code true} to enable, in this case the maximum number of jobs
* will be set to "optimal" number, see {@link #getOptimalParallelJobNum()}.
* <br>{@code false} to disable, the number of jobs will be set to 1.
*/
public void setParallelBuildOn(boolean on) throws CoreException { public void setParallelBuildOn(boolean on) throws CoreException {
if(isParallelBuildOn() == on) if (on) {
return; // set "optimal" jobs by default when enabling parallel build
if(on && !supportsParallelBuild()) setParallelizationNum(-1);
return; } else {
setParallelizationNum(1);
String curCmd = getParallelizationCmd(getParallelizationNum());
String args = getArgumentsAttribute();
String updatedArgs = removeCmd(args, curCmd);
if(!updatedArgs.equals(args)){
setArgumentsAttribute(updatedArgs);
} }
parallelBuildOn = Boolean.valueOf(on);
setDirty(true);
} }
public Set<String> contributeErrorParsers(Set<String> set){ public Set<String> contributeErrorParsers(Set<String> set){
@ -2638,6 +2742,7 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider
public boolean isExtensionBuildObject() { public boolean isExtensionBuildObject() {
return isExtensionElement(); return isExtensionElement();
} }
@Override @Override
public String toString() { public String toString() {
return getUniqueRealName(); return getUniqueRealName();

View file

@ -752,7 +752,7 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild
* E L E M E N T A T T R I B U T E R E A D E R S A N D W R I T E R S * E L E M E N T A T T R I B U T E R E A D E R S A N D W R I T E R S
*/ */
/* (non-Javadoc) /**
* Initialize the configuration information from an element in the * Initialize the configuration information from an element in the
* manifest file or provided by a dynamicElementProvider * manifest file or provided by a dynamicElementProvider
* *
@ -803,7 +803,7 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild
isTest = Boolean.valueOf(tmp).booleanValue(); isTest = Boolean.valueOf(tmp).booleanValue();
} }
/* (non-Javadoc) /**
* Initialize the configuration information from the XML element * Initialize the configuration information from the XML element
* specified in the argument * specified in the argument
* *
@ -1577,7 +1577,6 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild
} }
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.eclipse.cdt.core.build.managed.IConfiguration#setPostbuildStep(java.lang.String) * @see org.eclipse.cdt.core.build.managed.IConfiguration#setPostbuildStep(java.lang.String)
*/ */
@ -1785,7 +1784,7 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild
((FolderInfo)getRootFolderInfo()).resetOptionSettings(); ((FolderInfo)getRootFolderInfo()).resetOptionSettings();
} }
/* /**
* Create a resource configuration object for the passed-in file * Create a resource configuration object for the passed-in file
*/ */
public IResourceConfiguration createResourceConfiguration(IFile file) public IResourceConfiguration createResourceConfiguration(IFile file)
@ -1932,7 +1931,7 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild
return getRootFolderInfo().getToolFromInputExtension(sourceExtension); return getRootFolderInfo().getToolFromInputExtension(sourceExtension);
} }
/* /**
* The resource delta passed to the builder is not always up-to-date * The resource delta passed to the builder is not always up-to-date
* for the given configuration because between two builds of the same configuration * for the given configuration because between two builds of the same configuration
* any number of other configuration builds may occur * any number of other configuration builds may occur
@ -2004,7 +2003,7 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild
prefs.getBoolean(pref, false) : defaultValue; prefs.getBoolean(pref, false) : defaultValue;
} }
*/ */
/* /**
* this method is used for enabling/disabling the internal builder * this method is used for enabling/disabling the internal builder
* for the given configuration * for the given configuration
* *
@ -2121,7 +2120,7 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild
return null; return null;
} }
/* /**
* returns whether the internal builder is enabled * returns whether the internal builder is enabled
* @return boolean * @return boolean
*/ */
@ -2129,7 +2128,7 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild
return getBuilder().isInternalBuilder(); return getBuilder().isInternalBuilder();
} }
/* /**
* *
* sets the Internal Builder mode * sets the Internal Builder mode
* *
@ -2144,7 +2143,7 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild
} }
} }
/* /**
* returns the Internal Builder mode * returns the Internal Builder mode
* if true, internal builder will ignore build errors while building, * if true, internal builder will ignore build errors while building,
* otherwise it will stop at the first build error * otherwise it will stop at the first build error
@ -2156,73 +2155,73 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild
} }
/** /**
*
* sets the Internal Builder Parallel mode * sets the Internal Builder Parallel mode
*
* @param parallel if true, internal builder will use parallel mode * @param parallel if true, internal builder will use parallel mode
*
* @deprecated since CDT 9.0. Use {@link #setParallelDef(boolean)}
*/ */
@Deprecated
public void setInternalBuilderParallel(boolean parallel){ public void setInternalBuilderParallel(boolean parallel){
if(getInternalBuilderParallel() == parallel) setParallelDef(parallel);
return;
try {
getEditableBuilder().setParallelBuildOn(parallel);
} catch (CoreException e) {
}
} }
/** /**
* returns the Internal Builder parallel mode * returns the Internal Builder parallel mode
* if true, internal builder will work in parallel mode * if true, internal builder will work in parallel mode
* otherwise it will use only one thread * otherwise it will use only one thread
*
* @return boolean * @return boolean
*
* @deprecated since CDT 9.0. Use {@link #getParallelDef()}
*/ */
@Deprecated
public boolean getInternalBuilderParallel(){ public boolean getInternalBuilderParallel(){
return getBuilder().isParallelBuildOn(); return getParallelDef();
} }
/** /**
* @param parallel if true, internal builder will use parallel mode * Set parallel execution mode for the configuration's builder.
* @see Builder#setParallelBuildOn(boolean)
*
* @param parallel - the flag to enable or disable parallel mode.
*/ */
public void setParallelDef(boolean parallel){ public void setParallelDef(boolean parallel){
if(getParallelDef() == parallel) if(getParallelDef() == parallel)
return; return;
int num = getParallelNumber(); try {
if(num != 0){ getEditableBuilder().setParallelBuildOn(parallel);
setParallelNumber(-num); } catch (CoreException e) {
} else { ManagedBuilderCorePlugin.log(e);
if(parallel){
setParallelNumber(-1);
} else {
setParallelNumber(1);
}
} }
} }
/** /**
* @return boolean * Check if the configuration's builder is operating in parallel mode.
* @return {@code true} if parallel mode is enabled, {@code false} otherwise.
*/ */
public boolean getParallelDef(){ public boolean getParallelDef(){
int num = getBuilder().getParallelizationNum(); return getBuilder().isParallelBuildOn();
return num <= 0;
} }
/** /**
* sets number of Parallel threads * Sets maximum number of parallel threads/jobs to be used by builder.
*/
public void setParallelNumber(int n){
try {
getEditableBuilder().setParallelizationNum(n);
} catch (CoreException e) {
}
}
/**
* returns number of Parallel threads
* *
* @return int * @param jobs - maximum number of jobs or threads. For details how
* the number is interpreted see {@link Builder#setParallelizationNum(int)}.
*/
public void setParallelNumber(int jobs){
try {
getEditableBuilder().setParallelizationNum(jobs);
} catch (CoreException e) {
ManagedBuilderCorePlugin.log(e);
}
}
/**
* Returns maximum number of parallel threads/jobs used by the configuration's builder.
* @see #setParallelDef(boolean)
*
* @return - maximum number of parallel threads or jobs used by the builder.
*/ */
public int getParallelNumber(){ public int getParallelNumber(){
return getBuilder().getParallelizationNum(); return getBuilder().getParallelizationNum();

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2002, 2010 IBM Corporation and others. * Copyright (c) 2002, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -906,7 +906,6 @@ public class GeneratedMakefileBuilder extends ACBuilder {
} }
IPath makeCommand = new Path(makeCmd); IPath makeCommand = new Path(makeCmd);
if (makeCommand != null) {
String[] msgs = new String[2]; String[] msgs = new String[2];
msgs[0] = makeCommand.toString(); msgs[0] = makeCommand.toString();
msgs[1] = currentProject.getName(); msgs[1] = currentProject.getName();
@ -1144,7 +1143,6 @@ public class GeneratedMakefileBuilder extends ACBuilder {
addBuilderMarkers(epm); addBuilderMarkers(epm);
consoleOutStream.close(); consoleOutStream.close();
} }
}
} catch (Exception e) { } catch (Exception e) {
forgetLastBuiltState(); forgetLastBuiltState();
} finally { } finally {
@ -1196,7 +1194,7 @@ public class GeneratedMakefileBuilder extends ACBuilder {
boolean resumeOnErr, boolean resumeOnErr,
IProgressMonitor monitor) { IProgressMonitor monitor) {
boolean isParallel = ((Configuration)cfg).getInternalBuilderParallel(); boolean isParallel = ((Configuration)cfg).getParallelDef();
// Get the project and make sure there's a monitor to cancel the build // Get the project and make sure there's a monitor to cancel the build
IProject currentProject = cfg.getOwner().getProject(); IProject currentProject = cfg.getOwner().getProject();

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2007, 2010 Intel Corporation and others. * Copyright (c) 2007, 2011 Intel Corporation and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -44,6 +44,7 @@ import org.eclipse.cdt.managedbuilder.envvar.IConfigurationEnvironmentVariableSu
import org.eclipse.cdt.managedbuilder.macros.IConfigurationBuildMacroSupplier; import org.eclipse.cdt.managedbuilder.macros.IConfigurationBuildMacroSupplier;
import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IPath;
import org.osgi.framework.Version; import org.osgi.framework.Version;
@ -253,15 +254,23 @@ public class MultiConfiguration extends MultiItemsHolder implements
return s; return s;
} }
/* (non-Javadoc) /**
* @see org.eclipse.cdt.managedbuilder.core.IConfiguration#getBuildArguments() * @return build arguments if the arguments for all configurations match
* or {@code null} otherwise.
*/ */
public String getBuildArguments() { public String getBuildArguments() {
String s = fCfgs[0].getBuildArguments(); String args0 = fCfgs[0].getBuildArguments();
for (int i=1; i<fCfgs.length; i++) if (args0 == null)
if (! s.equals(fCfgs[i].getBuildArguments())) args0 = EMPTY_STR;
return EMPTY_STR;
return s; for (IConfiguration cfg : fCfgs) {
String args = cfg.getBuildArguments();
if (args == null)
args = EMPTY_STR;
if (!args0.equals(args))
return null;
}
return args0;
} }
/* (non-Javadoc) /* (non-Javadoc)
@ -1090,49 +1099,49 @@ public class MultiConfiguration extends MultiItemsHolder implements
} }
public boolean getParallelDef() { public boolean getParallelDef() {
for (int i=0; i<fCfgs.length; i++) for (IConfiguration cfg : fCfgs) {
if (fCfgs[i] instanceof Configuration) { if (cfg instanceof Configuration) {
if (!((Configuration)fCfgs[i]).getParallelDef()) if (!((Configuration)cfg).getParallelDef())
return false; return false;
} else } else
return false; return false;
}
return true; // all cfgs report true return true; // all cfgs report true
} }
public void setParallelDef(boolean def) { public void setParallelDef(boolean parallel) {
for (int i=0; i<fCfgs.length; i++) for (IConfiguration cfg : fCfgs) {
if (fCfgs[i] instanceof Configuration) if (cfg instanceof Configuration)
((Configuration)fCfgs[i]).setParallelDef(def); ((Configuration)cfg).setParallelDef(parallel);
}
} }
public int getParallelNumber() { public int getParallelNumber() {
int res = -1; int res = 0;
for (int i=0; i<fCfgs.length; i++) for (IConfiguration cfg : fCfgs) {
if (fCfgs[i] instanceof Configuration) { if (cfg instanceof Configuration) {
int x = ((Configuration)fCfgs[i]).getParallelNumber(); int num = ((Configuration)cfg).getParallelNumber();
if (res == -1) Assert.isTrue(num != 0); // can't be 0, see IMakeCommonBuildInfo.getParallelizationNum()
res = x;
else if (res != x) if (res == 0)
res = num;
else if (res != num)
return 0; // values are different ! return 0; // values are different !
} else } else
return 0; return 0;
return (res == -1 ? 0: res); // all cfgs report true }
return res; // all cfgs report same value
} }
public void setParallelNumber(int num) { public void setParallelNumber(int num) {
for (int i=0; i<fCfgs.length; i++) for (IConfiguration cfg : fCfgs) {
if (fCfgs[i] instanceof Configuration) if (cfg instanceof Configuration)
((Configuration)fCfgs[i]).setParallelNumber(num); ((Configuration)cfg).setParallelNumber(num);
}
} }
public boolean getInternalBuilderParallel() { public boolean getInternalBuilderParallel() {
for (int i=0; i<fCfgs.length; i++) return getParallelDef();
if (fCfgs[i] instanceof Configuration) {
if (!((Configuration)fCfgs[i]).getInternalBuilderParallel())
return false;
} else
return false;
return true; // all cfgs report true
} }
public boolean isInternalBuilderEnabled() { public boolean isInternalBuilderEnabled() {

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2004, 2010 QNX Software Systems and others. * Copyright (c) 2004, 2011 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -12,6 +12,7 @@ package org.eclipse.cdt.newmake.core;
import java.util.Map; import java.util.Map;
import org.eclipse.cdt.managedbuilder.internal.core.Builder;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IPath;
@ -42,10 +43,39 @@ public interface IMakeCommonBuildInfo {
void setStopOnError(boolean on) throws CoreException; void setStopOnError(boolean on) throws CoreException;
boolean supportsStopOnError(boolean on); boolean supportsStopOnError(boolean on);
/**
* @return the maximum number of parallel jobs to be used for build.
*/
int getParallelizationNum(); int getParallelizationNum();
void setParallelizationNum(int num) throws CoreException;
/**
* Sets maximum number of parallel threads/jobs to be used by builder.
* Note that this number can be interpreted by builder in a special way.
* @see Builder#setParallelizationNum(int)
*
* @param jobs - maximum number of jobs.
*/
void setParallelizationNum(int jobs) throws CoreException;
/**
* @return {@code true} if builder supports parallel build,
* {@code false} otherwise.
*/
boolean supportsParallelBuild(); boolean supportsParallelBuild();
/**
* @return {@code true} if builder support for parallel build is enabled,
* {@code false} otherwise.
*/
boolean isParallelBuildOn(); boolean isParallelBuildOn();
/**
* Set parallel execution mode for the builder.
* @see Builder#setParallelBuildOn(boolean)
*
* @param on - the flag to enable or disable parallel mode.
*/
void setParallelBuildOn(boolean on) throws CoreException; void setParallelBuildOn(boolean on) throws CoreException;
boolean isDefaultBuildCmd(); boolean isDefaultBuildCmd();

View file

@ -27,9 +27,10 @@ public class Messages extends NLS {
public static String BuilderSettingsTab_0; public static String BuilderSettingsTab_0;
public static String BuilderSettingsTab_1; public static String BuilderSettingsTab_1;
public static String BuilderSettingsTab_10; public static String BuilderSettingsTab_10;
public static String BuilderSettingsTab_11; public static String BuilderSettingsTab_EnableParallelBuild;
public static String BuilderSettingsTab_12; public static String BuilderSettingsTab_UseOptimalJobs;
public static String BuilderSettingsTab_13; public static String BuilderSettingsTab_UseUnlimitedJobs;
public static String BuilderSettingsTab_UseParallelJobs;
public static String BuilderSettingsTab_14; public static String BuilderSettingsTab_14;
public static String BuilderSettingsTab_15; public static String BuilderSettingsTab_15;
public static String BuilderSettingsTab_16; public static String BuilderSettingsTab_16;

View file

@ -31,9 +31,10 @@ BuilderSettingsTab_7=&Generate Makefiles automatically
BuilderSettingsTab_8=&Expand Env. Variable Refs in Makefiles BuilderSettingsTab_8=&Expand Env. Variable Refs in Makefiles
BuilderSettingsTab_9=Build settings BuilderSettingsTab_9=Build settings
BuilderSettingsTab_10=Stop on first build error BuilderSettingsTab_10=Stop on first build error
BuilderSettingsTab_11=Use parallel build BuilderSettingsTab_EnableParallelBuild=Enable parallel build
BuilderSettingsTab_12=Use optimal jobs number BuilderSettingsTab_UseOptimalJobs=Use number of processors ({0})
BuilderSettingsTab_13=Use parallel jobs: BuilderSettingsTab_UseParallelJobs=Use parallel jobs:
BuilderSettingsTab_UseUnlimitedJobs=Use unlimited jobs
BuilderSettingsTab_14=Workbench Build Behavior BuilderSettingsTab_14=Workbench Build Behavior
BuilderSettingsTab_15=Workbench build type: BuilderSettingsTab_15=Workbench build type:
BuilderSettingsTab_16=Make build target: BuilderSettingsTab_16=Make build target:

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2007, 2010 Intel Corporation and others. * Copyright (c) 2007, 2011 Intel Corporation and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -11,6 +11,8 @@
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.managedbuilder.ui.properties; package org.eclipse.cdt.managedbuilder.ui.properties;
import java.text.MessageFormat;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICMultiConfigDescription; import org.eclipse.cdt.core.settings.model.ICMultiConfigDescription;
import org.eclipse.cdt.core.settings.model.ICMultiItemsHolder; import org.eclipse.cdt.core.settings.model.ICMultiItemsHolder;
@ -18,7 +20,6 @@ import org.eclipse.cdt.core.settings.model.ICResourceDescription;
import org.eclipse.cdt.managedbuilder.core.IBuilder; import org.eclipse.cdt.managedbuilder.core.IBuilder;
import org.eclipse.cdt.managedbuilder.core.IConfiguration; import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.IMultiConfiguration; import org.eclipse.cdt.managedbuilder.core.IMultiConfiguration;
import org.eclipse.cdt.managedbuilder.internal.buildmodel.BuildProcessManager;
import org.eclipse.cdt.managedbuilder.internal.core.Builder; import org.eclipse.cdt.managedbuilder.internal.core.Builder;
import org.eclipse.cdt.managedbuilder.internal.core.Configuration; import org.eclipse.cdt.managedbuilder.internal.core.Configuration;
import org.eclipse.cdt.managedbuilder.internal.core.MultiConfiguration; import org.eclipse.cdt.managedbuilder.internal.core.MultiConfiguration;
@ -51,6 +52,8 @@ import org.eclipse.swt.widgets.Widget;
* @noinstantiate This class is not intended to be instantiated by clients. * @noinstantiate This class is not intended to be instantiated by clients.
*/ */
public class BuildBehaviourTab extends AbstractCBuildPropertyTab { public class BuildBehaviourTab extends AbstractCBuildPropertyTab {
private static final int SPINNER_MAX_VALUE = 10000;
private static final int SPINNER_MIN_VALUE = 2;
private static final int TRI_STATES_SIZE = 4; private static final int TRI_STATES_SIZE = 4;
// Widgets // Widgets
@ -58,9 +61,10 @@ public class BuildBehaviourTab extends AbstractCBuildPropertyTab {
private Button b_stopOnError; // 3 private Button b_stopOnError; // 3
private Button b_parallel; // 3 private Button b_parallel; // 3
private Button b_parallelOpt; private Button b_parallelOptimal;
private Button b_parallelNum; private Button b_parallelSpecific;
private Spinner parallelProcesses; private Button b_parallelUnlimited;
private Spinner s_parallelNumber;
private Label title2; private Label title2;
private Button b_autoBuild; //3 private Button b_autoBuild; //3
@ -70,11 +74,11 @@ public class BuildBehaviourTab extends AbstractCBuildPropertyTab {
private Button b_cmdClean; // 3 private Button b_cmdClean; // 3
private Text t_cmdClean; private Text t_cmdClean;
private IBuilder bldr; private Builder bldr;
private IConfiguration icfg; private IConfiguration icfg;
private boolean canModify = true; private boolean canModify = true;
protected final int cpuNumber = BuildProcessManager.checkCPUNumber(); protected final int cpuNumber = Runtime.getRuntime().availableProcessors();
@Override @Override
public void createControls(Composite parent) { public void createControls(Composite parent) {
@ -110,7 +114,7 @@ public class BuildBehaviourTab extends AbstractCBuildPropertyTab {
gl.marginHeight = 0; gl.marginHeight = 0;
c2.setLayout(gl); c2.setLayout(gl);
b_parallel = setupCheck(c2, Messages.BuilderSettingsTab_11, 1, GridData.BEGINNING); b_parallel = setupCheck(c2, Messages.BuilderSettingsTab_EnableParallelBuild, 1, GridData.BEGINNING);
Composite c3 = new Composite(g3, SWT.NONE); Composite c3 = new Composite(g3, SWT.NONE);
setupControl(c3, 1, GridData.FILL_BOTH); setupControl(c3, 1, GridData.FILL_BOTH);
@ -120,39 +124,60 @@ public class BuildBehaviourTab extends AbstractCBuildPropertyTab {
gl.marginHeight = 0; gl.marginHeight = 0;
c3.setLayout(gl); c3.setLayout(gl);
b_parallelOpt= new Button(c3, SWT.RADIO); b_parallelOptimal= new Button(c3, SWT.RADIO);
b_parallelOpt.setText(Messages.BuilderSettingsTab_12); b_parallelOptimal.setText(MessageFormat.format(Messages.BuilderSettingsTab_UseOptimalJobs, 1));
setupControl(b_parallelOpt, 2, GridData.BEGINNING); setupControl(b_parallelOptimal, 2, GridData.BEGINNING);
((GridData)(b_parallelOpt.getLayoutData())).horizontalIndent = 15; ((GridData)(b_parallelOptimal.getLayoutData())).horizontalIndent = 15;
b_parallelOpt.addSelectionListener(new SelectionAdapter() { b_parallelOptimal.addSelectionListener(new SelectionAdapter() {
@Override @Override
public void widgetSelected(SelectionEvent event) { public void widgetSelected(SelectionEvent event) {
setParallelDef(b_parallelOpt.getSelection()); if (b_parallelOptimal.getSelection()) {
setParallelDef(true);
setParallelNumber(-1);
updateButtons(); updateButtons();
}
}}); }});
b_parallelNum= new Button(c3, SWT.RADIO); b_parallelSpecific= new Button(c3, SWT.RADIO);
b_parallelNum.setText(Messages.BuilderSettingsTab_13); b_parallelSpecific.setText(Messages.BuilderSettingsTab_UseParallelJobs);
setupControl(b_parallelNum, 1, GridData.BEGINNING); setupControl(b_parallelSpecific, 1, GridData.BEGINNING);
((GridData)(b_parallelNum.getLayoutData())).horizontalIndent = 15; ((GridData)(b_parallelSpecific.getLayoutData())).horizontalIndent = 15;
b_parallelNum.addSelectionListener(new SelectionAdapter() { b_parallelSpecific.addSelectionListener(new SelectionAdapter() {
@Override @Override
public void widgetSelected(SelectionEvent event) { public void widgetSelected(SelectionEvent event) {
setParallelDef(!b_parallelNum.getSelection()); if (b_parallelSpecific.getSelection()) {
setParallelDef(true);
setParallelNumber(s_parallelNumber.getSelection());
updateButtons(); updateButtons();
}
}}); }});
parallelProcesses = new Spinner(c3, SWT.BORDER); s_parallelNumber = new Spinner(c3, SWT.BORDER);
setupControl(parallelProcesses, 1, GridData.BEGINNING); setupControl(s_parallelNumber, 1, GridData.BEGINNING);
parallelProcesses.setValues(cpuNumber, 1, 10000, 0, 1, 10); s_parallelNumber.setValues(cpuNumber, SPINNER_MIN_VALUE, SPINNER_MAX_VALUE, 0, 1, 10);
parallelProcesses.addSelectionListener(new SelectionAdapter () { s_parallelNumber.addSelectionListener(new SelectionAdapter () {
@Override @Override
public void widgetSelected(SelectionEvent e) { public void widgetSelected(SelectionEvent e) {
setParallelNumber(parallelProcesses.getSelection()); setParallelDef(true);
setParallelNumber(s_parallelNumber.getSelection());
updateButtons(); updateButtons();
} }
}); });
b_parallelUnlimited= new Button(c3, SWT.RADIO);
b_parallelUnlimited.setText(Messages.BuilderSettingsTab_UseUnlimitedJobs);
setupControl(b_parallelUnlimited, 2, GridData.BEGINNING);
((GridData)(b_parallelUnlimited.getLayoutData())).horizontalIndent = 15;
b_parallelUnlimited.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
if (b_parallelUnlimited.getSelection()) {
setParallelDef(true);
setParallelNumber(Builder.UNLIMITED_JOBS);
updateButtons();
}
}});
// Workbench behaviour group // Workbench behaviour group
AccessibleListener makeTargetLabelAccessibleListener = new AccessibleAdapter() { AccessibleListener makeTargetLabelAccessibleListener = new AccessibleAdapter() {
@Override @Override
@ -191,6 +216,7 @@ public class BuildBehaviourTab extends AbstractCBuildPropertyTab {
} }
/** /**
* Calculate enablements when multiple configurations selected on property page.
* *
* @return: * @return:
* Mode 0: * Mode 0:
@ -202,55 +228,51 @@ public class BuildBehaviourTab extends AbstractCBuildPropertyTab {
* 0: isStopOnError * 0: isStopOnError
* 1: supportsStopOnError(true) * 1: supportsStopOnError(true)
* 2: bld.supportsStopOnError(false) * 2: bld.supportsStopOnError(false)
* 3: cfg.getInternalBuilderParallel() * 3: N/A
* Mode 2: * Mode 2:
* 0: b.isAutoBuildEnable() * 0: b.isAutoBuildEnable()
* 1: b.isIncrementalBuildEnabled() * 1: b.isIncrementalBuildEnabled()
* 2: b.isCleanBuildEnabled() * 2: b.isCleanBuildEnabled()
* 3: getParallelDef() * 3: N/A
*/ */
static int[] calc3states(ICPropertyProvider p, static int[] calc3states(ICPropertyProvider p, IConfiguration mcfg, int mode) {
IConfiguration c, if (p.isMultiCfg() && mcfg instanceof ICMultiItemsHolder) {
int mode) { boolean m0 = (mode == 0);
if (p.isMultiCfg() && boolean m1 = (mode == 1);
c instanceof ICMultiItemsHolder)
{
boolean p0 = (mode == 0);
boolean p1 = (mode == 1);
IConfiguration[] cfs = (IConfiguration[])((ICMultiItemsHolder)c).getItems(); IConfiguration[] cfgs = (IConfiguration[])((ICMultiItemsHolder)mcfg).getItems();
IBuilder b = cfs[0].getBuilder(); IBuilder bldr0 = cfgs[0].getBuilder();
int[] res = new int[TRI_STATES_SIZE]; int[] res = new int[TRI_STATES_SIZE];
boolean[] x = new boolean[TRI_STATES_SIZE]; boolean[] b = new boolean[TRI_STATES_SIZE];
x[0] = p0 ? b.isManagedBuildOn() : b[0] = m0 ? bldr0.isManagedBuildOn() :
(p1 ? b.isStopOnError() : b.isAutoBuildEnable()); (m1 ? bldr0.isStopOnError() : bldr0.isAutoBuildEnable());
x[1] = p0 ? b.isDefaultBuildCmd(): b[1] = m0 ? bldr0.isDefaultBuildCmd():
(p1 ? b.supportsStopOnError(true) : b.isIncrementalBuildEnabled() ); (m1 ? bldr0.supportsStopOnError(true) : bldr0.isIncrementalBuildEnabled() );
x[2] = p0 ? b.canKeepEnvironmentVariablesInBuildfile() : b[2] = m0 ? bldr0.canKeepEnvironmentVariablesInBuildfile() :
(p1 ? b.supportsStopOnError(false) : b.isCleanBuildEnabled()); (m1 ? bldr0.supportsStopOnError(false) : bldr0.isCleanBuildEnabled());
x[3] = p0 ? b.keepEnvironmentVariablesInBuildfile() : b[3] = m0 ? bldr0.keepEnvironmentVariablesInBuildfile() : false;
( p1 ? ((Configuration)cfs[0]).getInternalBuilderParallel() : getParallelDef(c)); for (int i=1; i<cfgs.length; i++) {
for (int i=1; i<cfs.length; i++) { IBuilder bldr = cfgs[i].getBuilder();
b = cfs[i].getBuilder(); if (b[0] != (m0 ? bldr.isManagedBuildOn() :
if (x[0] != (p0 ? b.isManagedBuildOn() : (m1 ? bldr.isStopOnError() : bldr.isAutoBuildEnable())))
(p1 ? b.isStopOnError() : b.isAutoBuildEnable())))
res[0] = TRI_UNKNOWN; res[0] = TRI_UNKNOWN;
if (x[1] != (p0 ? b.isDefaultBuildCmd() : if (b[1] != (m0 ? bldr.isDefaultBuildCmd() :
(p1 ? b.supportsStopOnError(true) : b.isIncrementalBuildEnabled()))) (m1 ? bldr.supportsStopOnError(true) : bldr.isIncrementalBuildEnabled())))
res[1] = TRI_UNKNOWN; res[1] = TRI_UNKNOWN;
if (x[2] != (p0 ? b.canKeepEnvironmentVariablesInBuildfile() : if (b[2] != (m0 ? bldr.canKeepEnvironmentVariablesInBuildfile() :
(p1 ? b.supportsStopOnError(false) : b.isCleanBuildEnabled()))) (m1 ? bldr.supportsStopOnError(false) : bldr.isCleanBuildEnabled())))
res[2] = TRI_UNKNOWN; res[2] = TRI_UNKNOWN;
if (x[3] != (p0 ? b.keepEnvironmentVariablesInBuildfile() : if (b[3] != (m0 ? bldr.keepEnvironmentVariablesInBuildfile() : false)) {
(p1 ? ((Configuration)cfs[i]).getInternalBuilderParallel() : getParallelDef(c))))
res[3] = TRI_UNKNOWN; res[3] = TRI_UNKNOWN;
} }
}
for (int i=0; i<TRI_STATES_SIZE; i++) { for (int i=0; i<TRI_STATES_SIZE; i++) {
if (res[i] != TRI_UNKNOWN) if (res[i] != TRI_UNKNOWN)
res[i] = x[i] ? TRI_YES : TRI_NO; res[i] = b[i] ? TRI_YES : TRI_NO;
} }
return res; return res;
} else }
return null; return null;
} }
@ -259,10 +281,11 @@ public class BuildBehaviourTab extends AbstractCBuildPropertyTab {
*/ */
@Override @Override
protected void updateButtons() { protected void updateButtons() {
bldr = icfg.getEditableBuilder(); bldr = (Builder) icfg.getEditableBuilder();
canModify = false; canModify = false;
int[] extStates = calc3states(page, icfg, 1); int[] extStates = calc3states(page, icfg, 1);
// Stop on error
if (extStates != null) { if (extStates != null) {
setTriSelection(b_stopOnError, extStates[0]); setTriSelection(b_stopOnError, extStates[0]);
b_stopOnError.setEnabled( b_stopOnError.setEnabled(
@ -274,39 +297,21 @@ public class BuildBehaviourTab extends AbstractCBuildPropertyTab {
bldr.supportsStopOnError(true) && bldr.supportsStopOnError(true) &&
bldr.supportsStopOnError(false)); bldr.supportsStopOnError(false));
} }
// parallel
if (extStates == null) // no extended states
setTriSelection(b_parallel, getInternalBuilderParallel());
else
setTriSelection(b_parallel, extStates[3]);
int n = getParallelNumber();
if (n < 0) n = -n;
parallelProcesses.setSelection(n);
b_parallel.setVisible(bldr.supportsParallelBuild()); updateParallelBlock();
b_parallelOpt.setVisible(bldr.supportsParallelBuild());
b_parallelNum.setVisible(bldr.supportsParallelBuild());
parallelProcesses.setVisible(bldr.supportsParallelBuild());
// Build commands
extStates = calc3states(page, icfg, 2); extStates = calc3states(page, icfg, 2);
if (extStates == null) { if (extStates != null) {
setTriSelection(b_autoBuild, bldr.isAutoBuildEnable()); // multiple configurations selected
setTriSelection(b_cmdBuild, bldr.isIncrementalBuildEnabled());
setTriSelection(b_cmdClean, bldr.isCleanBuildEnabled());
b_parallelOpt.setSelection(getParallelDef(icfg));
b_parallelNum.setSelection(!getParallelDef(icfg));
} else {
setTriSelection(b_autoBuild, extStates[0]); setTriSelection(b_autoBuild, extStates[0]);
setTriSelection(b_cmdBuild, extStates[1]); setTriSelection(b_cmdBuild, extStates[1]);
setTriSelection(b_cmdClean, extStates[2]); setTriSelection(b_cmdClean, extStates[2]);
if (extStates[3] == TRI_UNKNOWN) {
b_parallelOpt.setSelection(false);
b_parallelNum.setSelection(false);
} else { } else {
b_parallelOpt.setSelection(getParallelDef(icfg)); setTriSelection(b_autoBuild, bldr.isAutoBuildEnable());
b_parallelNum.setSelection(!getParallelDef(icfg)); setTriSelection(b_cmdBuild, bldr.isIncrementalBuildEnabled());
} setTriSelection(b_cmdClean, bldr.isCleanBuildEnabled());
} }
if (page.isMultiCfg()) { if (page.isMultiCfg()) {
@ -321,12 +326,6 @@ public class BuildBehaviourTab extends AbstractCBuildPropertyTab {
} }
boolean external = ! isInternalBuilderEnabled(); boolean external = ! isInternalBuilderEnabled();
boolean parallel = b_parallel.getSelection();
b_parallelNum.setEnabled(parallel);
b_parallelOpt.setEnabled(parallel);
parallelProcesses.setEnabled(parallel & b_parallelNum.getSelection());
title2.setVisible(external); title2.setVisible(external);
t_autoBuild.setVisible(external); t_autoBuild.setVisible(external);
((Control)t_autoBuild.getData()).setVisible(external); ((Control)t_autoBuild.getData()).setVisible(external);
@ -343,6 +342,79 @@ public class BuildBehaviourTab extends AbstractCBuildPropertyTab {
canModify = true; canModify = true;
} }
private void updateParallelBlock() {
// note: for multi-config selection bldr is from Active cfg
boolean isParallelSupported = bldr.supportsParallelBuild();
boolean isParallelOn = bldr.isParallelBuildOn();
int triSelection = isParallelOn ? TRI_YES : TRI_NO;
int parallelizationNumInternal = bldr.getParallelizationNumAttribute();
int optimalParallelNumber = bldr.getOptimalParallelJobNum();
int parallelNumber = bldr.getParallelizationNum();
if (icfg instanceof ICMultiItemsHolder) {
IConfiguration[] cfgs = (IConfiguration[])((ICMultiItemsHolder)icfg).getItems();
boolean isAnyParallelOn = isParallelOn;
boolean isAnyParallelSupported = isParallelSupported;
boolean isParallelDiffers = false;
for (IConfiguration cfg : cfgs) {
Builder builder = (Builder) cfg.getBuilder();
isParallelDiffers = isParallelDiffers
|| builder.isParallelBuildOn() != isParallelOn
|| builder.getParallelizationNumAttribute() != parallelizationNumInternal;
isAnyParallelOn = isAnyParallelOn || builder.isParallelBuildOn();
isAnyParallelSupported = isAnyParallelSupported || builder.supportsParallelBuild();
}
// reset initial display to "optimal" to enhance user experience:
if ((!isParallelSupported && isAnyParallelSupported) // parallel is supported by other than Active cfg
|| (!isParallelOn && isAnyParallelOn) // prevent showing the 1 job as parallel in the spinner
) {
isParallelSupported = true;
parallelizationNumInternal = -optimalParallelNumber;
parallelNumber = optimalParallelNumber;
}
if (isParallelSupported && isParallelDiffers) {
triSelection = TRI_UNKNOWN;
}
}
b_parallel.setVisible(isParallelSupported);
b_parallelOptimal.setVisible(isParallelSupported);
b_parallelSpecific.setVisible(isParallelSupported);
b_parallelUnlimited.setVisible(isParallelSupported);
s_parallelNumber.setVisible(isParallelSupported);
if (isParallelSupported) {
setTriSelection(b_parallel, triSelection);
boolean isParallelSelected = b_parallel.getSelection();
b_parallelOptimal.setText(MessageFormat.format(Messages.BuilderSettingsTab_UseOptimalJobs, optimalParallelNumber));
b_parallelOptimal.setEnabled(isParallelSelected);
b_parallelSpecific.setEnabled(isParallelSelected);
b_parallelUnlimited.setEnabled(isParallelSelected);
if (isParallelSelected) {
boolean isOptimal = parallelizationNumInternal <= 0;
boolean isUnlimited = parallelizationNumInternal == Builder.UNLIMITED_JOBS;
b_parallelOptimal.setSelection(isOptimal);
b_parallelSpecific.setSelection(!isOptimal && !isUnlimited);
b_parallelUnlimited.setSelection(isUnlimited);
s_parallelNumber.setEnabled(b_parallelSpecific.getEnabled() && b_parallelSpecific.getSelection());
s_parallelNumber.setSelection(s_parallelNumber.isEnabled() ? parallelNumber : optimalParallelNumber);
} else {
b_parallelOptimal.setSelection(true);
b_parallelSpecific.setSelection(false);
b_parallelUnlimited.setSelection(false);
s_parallelNumber.setEnabled(false);
s_parallelNumber.setSelection(optimalParallelNumber);
}
}
}
/** /**
* Sets up text + corresponding button * Sets up text + corresponding button
* Checkbox can be implemented either by Button or by TriButton * Checkbox can be implemented either by Button or by TriButton
@ -446,7 +518,7 @@ public class BuildBehaviourTab extends AbstractCBuildPropertyTab {
} }
b2.setStopOnError(b1.isStopOnError()); b2.setStopOnError(b1.isStopOnError());
b2.setParallelBuildOn(b1.isParallelBuildOn()); b2.setParallelBuildOn(b1.isParallelBuildOn());
b2.setParallelizationNum(b1.getParallelizationNum()); b2.setParallelizationNum(((Builder) b1).getParallelizationNumAttribute());
if (b2.canKeepEnvironmentVariablesInBuildfile()) if (b2.canKeepEnvironmentVariablesInBuildfile())
b2.setKeepEnvironmentVariablesInBuildfile(b1.keepEnvironmentVariablesInBuildfile()); b2.setKeepEnvironmentVariablesInBuildfile(b1.keepEnvironmentVariablesInBuildfile());
((Builder)b2).setBuildPath(((Builder)b1).getBuildPathAttribute()); ((Builder)b2).setBuildPath(((Builder)b1).getBuildPathAttribute());
@ -488,14 +560,6 @@ public class BuildBehaviourTab extends AbstractCBuildPropertyTab {
updateData(getResDesc()); updateData(getResDesc());
} }
private static boolean getParallelDef(IConfiguration cfg) {
if (cfg instanceof Configuration)
return ((Configuration)cfg).getParallelDef();
if (cfg instanceof IMultiConfiguration)
return ((IMultiConfiguration)cfg).getParallelDef();
return false;
}
private void setParallelDef(boolean def) { private void setParallelDef(boolean def) {
if (icfg instanceof Configuration) if (icfg instanceof Configuration)
((Configuration)icfg).setParallelDef(def); ((Configuration)icfg).setParallelDef(def);
@ -503,13 +567,6 @@ public class BuildBehaviourTab extends AbstractCBuildPropertyTab {
((IMultiConfiguration)icfg).setParallelDef(def); ((IMultiConfiguration)icfg).setParallelDef(def);
} }
private int getParallelNumber() {
if (icfg instanceof Configuration)
return ((Configuration)icfg).getParallelNumber();
if (icfg instanceof IMultiConfiguration)
return ((IMultiConfiguration)icfg).getParallelNumber();
return 0;
}
private void setParallelNumber(int num) { private void setParallelNumber(int num) {
if (icfg instanceof Configuration) if (icfg instanceof Configuration)
((Configuration)icfg).setParallelNumber(num); ((Configuration)icfg).setParallelNumber(num);
@ -517,14 +574,6 @@ public class BuildBehaviourTab extends AbstractCBuildPropertyTab {
((IMultiConfiguration)icfg).setParallelNumber(num); ((IMultiConfiguration)icfg).setParallelNumber(num);
} }
private boolean getInternalBuilderParallel() {
if (icfg instanceof Configuration)
return ((Configuration)icfg).getInternalBuilderParallel();
if (icfg instanceof IMultiConfiguration)
return ((IMultiConfiguration)icfg).getInternalBuilderParallel();
return false;
}
private boolean isInternalBuilderEnabled() { private boolean isInternalBuilderEnabled() {
if (icfg instanceof Configuration) if (icfg instanceof Configuration)
return ((Configuration)icfg).isInternalBuilderEnabled(); return ((Configuration)icfg).isInternalBuilderEnabled();

View file

@ -171,7 +171,7 @@ public class BuilderSettingsTab extends AbstractCBuildPropertyTab {
canEnableInternalBuilder(true) && canEnableInternalBuilder(true) &&
canEnableInternalBuilder(false)); canEnableInternalBuilder(false));
t_buildCmd.setText(getMC()); t_buildCmd.setText(getMakeCommand());
if (page.isMultiCfg()) { if (page.isMultiCfg()) {
group_dir.setVisible(false); group_dir.setVisible(false);
@ -293,11 +293,14 @@ public class BuilderSettingsTab extends AbstractCBuildPropertyTab {
/** /**
* @return make command * @return make command
*/ */
private String getMC() { private String getMakeCommand() {
String makeCommand = bldr.getCommand(); String makeCommand = icfg.getBuildCommand();
String makeArgs = bldr.getArguments(); String makeArgs = icfg.getBuildArguments();
if (makeArgs != null) { makeCommand += " " + makeArgs; } //$NON-NLS-1$
return makeCommand; if (!(makeCommand.length() == 0) && makeArgs != null) {
return makeCommand + " " + makeArgs; //$NON-NLS-1$
}
return EMPTY_STR;
} }
/** /**
* Performs common settings for all controls * Performs common settings for all controls