diff --git a/build/org.eclipse.cdt.managedbuilder.core/schema/buildDefinitions.exsd b/build/org.eclipse.cdt.managedbuilder.core/schema/buildDefinitions.exsd index 391e00f5984..e8a56781bf9 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/schema/buildDefinitions.exsd +++ b/build/org.eclipse.cdt.managedbuilder.core/schema/buildDefinitions.exsd @@ -1757,8 +1757,27 @@ If this attribute is not specified, MBS will assume that there are no reserved m - specifies the "parallel build" builder option. -If the builder supports specifying custom number of parallel jobs, the option definition may contain "*" the Build System sill substitute the "*" with the number of parallel threads to be used. + Specifies the command for "parallel build". +If the builder supports specifying custom number of parallel jobs the option definition may contain "*". The Build System will substitute the "*" with the number of parallel threads to be used. In case of "unlimited" jobs jobs number will be omitted. +For example, builder representing GNU make would define parallelBuildCmd as "-j*". + + + + + + + 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 "parallelizationNumber" attribute. If "parallelizationNumber" is not defined "optimal" value will be used. + + + + + + + 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 "optimal" or "unlimited" are recognized: +- number 1 will cause parallel build to be turned off, +- "optimal" will set maximum number of jobs to number of processors on the system, +- "unlimited" will make builder to run as many threads/jobs as possible. diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IBuilder.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IBuilder.java index 3a60bedc114..08ca4855ad7 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IBuilder.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IBuilder.java @@ -75,14 +75,17 @@ public interface IBuilder extends IHoldsOptions, IMakeBuilderInfo { 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_CUSTOMIZED_ERROR_PARSERS = "customizedErrorParsers"; //$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_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_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_START = "["; //$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_CLEAN = "clean"; //$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$ - - /** - * @since 8.0 - */ + /** @since 8.0 */ static final String ATTRIBUTE_BUILD_RUNNER = "buildRunner"; //$NON-NLS-1$ /** diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IMultiConfiguration.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IMultiConfiguration.java index a35d89b66cd..77a092baff5 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IMultiConfiguration.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IMultiConfiguration.java @@ -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 * are made available under the terms of the Eclipse Public License v1.0 * 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.managedbuilder.buildproperties.IBuildProperty; 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. * @noimplement This interface is not intended to be implemented by clients. */ 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(); - void setParallelDef(boolean def); - - int getParallelNumber(); - void setParallelNumber(int num); + /** + * 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(); + + /** + * 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 isInternalBuilderEnabled(); diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/InternalBuildRunner.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/InternalBuildRunner.java index b8f525e1a1b..f50ce9993aa 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/InternalBuildRunner.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/InternalBuildRunner.java @@ -65,7 +65,7 @@ public class InternalBuildRunner extends AbstractBuildRunner { public boolean invokeBuild(int kind, IProject project, IConfiguration configuration, IBuilder builder, IConsole console, IMarkerGenerator markerGenerator, IncrementalProjectBuilder projectBuilder, IProgressMonitor monitor) throws CoreException { - boolean isParallel = builder.isParallelBuildOn() && builder.getParallelizationNum() > 1; + boolean isParallel = builder.getParallelizationNum() > 1; // boolean buildIncrementaly = true; boolean resumeOnErr = !builder.isStopOnError(); @@ -173,8 +173,7 @@ public class InternalBuildRunner extends AbstractBuildRunner { break; case IBuildModelBuilder.STATUS_ERROR_LAUNCH: default: - buf.append(ManagedMakeMessages - .getResourceString(BUILD_FAILED_ERR)); + buf.append(ManagedMakeMessages.getResourceString(BUILD_FAILED_ERR)); break; } 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 = null; // Generate any error markers that the build has discovered - monitor.subTask(ManagedMakeMessages - .getResourceString(MARKERS)); + monitor.subTask(ManagedMakeMessages.getResourceString(MARKERS)); bsMngr.setProjectBuildState(project, pBS); } else { 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 index 28a31ae2d5a..5525b20774b 100644 --- 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 @@ -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 * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -11,41 +11,27 @@ 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.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.Vector; 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.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; + protected Vector processes; + protected int maxProcesses; /** * Initializes process manager @@ -59,7 +45,7 @@ public class BuildProcessManager { err = _err; show = _show; maxProcesses = _procNumber; - processes = new ProcessLauncher[maxProcesses]; + processes = new Vector(Math.min(10, maxProcesses), 10); } /** @@ -79,18 +65,19 @@ public class BuildProcessManager { * @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; - } + for (int i = 0; i < maxProcesses; i++) { + if (i >= processes.size()) { + ProcessLauncher process = new ProcessLauncher(cmd.getCommand(), cmd.getArgs(), mapToStringArray(cmd.getEnvironment()), cwd, out, err, monitor, show); + processes.add(process); + process.launch(); + return process; + } - - 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]; + if (processes.get(i).queryState() == ProcessLauncher.STATE_DONE) { + ProcessLauncher process = new ProcessLauncher(cmd.getCommand(), cmd.getArgs(), mapToStringArray(cmd.getEnvironment()), cwd, out, err, monitor, show); + processes.set(i, process); + process.launch(); + return process; } } return null; @@ -102,36 +89,37 @@ public class BuildProcessManager { * 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]; - } - } + for (ProcessLauncher process : processes) { + int state = process.queryState(); + if (state != ProcessLauncher.STATE_RUNNING && state != ProcessLauncher.STATE_DONE) + return process; } - return result; + return null; } /** * Checks states of all currently running processes. */ public boolean hasEmpty() { - for (int i = 0; i < maxProcesses; i++) { - if (processes[i] == null) + if (processes.size() < maxProcesses) + return true; + + for (ProcessLauncher process : processes) { + if (process.queryState() != ProcessLauncher.STATE_RUNNING) return true; - else { - if (processes[i].queryState() != ProcessLauncher.STATE_RUNNING) - return true; - } } return false; } + /** + * Returns maximum threads used up to that point + */ + public int getThreadsUsed() { + return processes.size(); + } + + /** * Converts map to strings array @@ -152,40 +140,10 @@ public class BuildProcessManager { /** * @return Number of processors detected + * @deprecated since CDT 9.0 - just use Runtime.getRuntime().availableProcessors() */ + @Deprecated 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$ - 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; + return Runtime.getRuntime().availableProcessors(); } } \ No newline at end of file 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 index 782c3d59075..29a5629f764 100644 --- 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 @@ -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 * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -17,6 +17,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; +import java.util.Vector; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.managedbuilder.buildmodel.IBuildCommand; @@ -205,18 +206,16 @@ public class ParallelBuilder { 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(); + 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)); + BuildProcessManager buildProcessManager = new BuildProcessManager(out, err, true, threads); + builder.dispatch(buildProcessManager); + lastThreadsUsed = buildProcessManager.getThreadsUsed(); monitor.done(); - lastThreadsUsed = threads; return IBuildModelBuilder.STATUS_OK; } @@ -295,10 +294,8 @@ public class ParallelBuilder { * 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 maxProcesses = mgr.getMaxProcesses(); + Vector active = new Vector(Math.min(maxProcesses, 10), 10); int activeCount = 0; int maxLevel = 0; @@ -332,9 +329,8 @@ public class ParallelBuilder { 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(); + for (ActiveBuildStep buildStep : active) { + ProcessLauncher pl = buildStep.getLauncher(); if (pl == null) continue; if (pl.queryState() == ProcessLauncher.STATE_DONE) { // If process has terminated with error, break loop @@ -345,8 +341,8 @@ public class ParallelBuilder { break main_loop; } // Try to launch next command for the current active step - if (active[i].isDone()) continue; - if (active[i].launchNextCmd(mgr)) { + if (buildStep.isDone()) continue; + if (buildStep.launchNextCmd(mgr)) { // Command has been launched. Check if process pool is not maximized yet if (!mgr.hasEmpty()) { proceed = false; @@ -354,7 +350,7 @@ public class ParallelBuilder { } } else { // Command has not been launched: step complete - refreshOutputs(active[i].getStep()); + refreshOutputs(buildStep.getStep()); activeCount--; monitor.worked(1); } @@ -373,7 +369,7 @@ public class ParallelBuilder { } // 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 Iterator iter = queue.iterator(); @@ -381,8 +377,8 @@ public class ParallelBuilder { while (iter.hasNext()) { BuildQueueElement elem = iter.next(); - // If "active steps" list is full, then break loop - if (activeCount == active.length) + // If "active steps" list reaches maximum, then break loop + if (activeCount == maxProcesses) break; // If current element's level exceeds maximum level of currently built @@ -391,14 +387,13 @@ public class ParallelBuilder { 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 + for (IBuildResource bldRes : elem.getStep().getInputResources()) { + IBuildStep step = bldRes.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()) { + if (step != step.getBuildDescription().getInputStep()) { + for (ActiveBuildStep buildStep : active) { + if (buildStep != null && buildStep.getStep().equals(step) && !buildStep.isDone()) { built = false; break; } @@ -417,10 +412,21 @@ public class ParallelBuilder { // 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++; + for (int i = 0; i < maxProcesses; i++) { + if (i >= active.size()) { + // add new item + 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; } } diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Builder.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Builder.java index bb9f105b626..f1a8bbefdd4 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Builder.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Builder.java @@ -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.LanguageSettingEntriesSerializer; 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.ExternalBuildRunner; 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.IConfiguration; 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.core.resources.IProject; import org.eclipse.core.resources.IncrementalProjectBuilder; +import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; @@ -79,7 +80,7 @@ import org.eclipse.core.variables.VariablesPlugin; import org.osgi.framework.Version; public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider, IRealBuildObjectAssociation { - + public static final int UNLIMITED_JOBS = Integer.MAX_VALUE; private static final String EMPTY_STRING = ""; //$NON-NLS-1$ // Superclass @@ -119,10 +120,12 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider private HashMap customBuildProperties; // private Boolean isWorkspaceBuildPath; private String ignoreErrCmd; - private String parallelBuildCmd; private Boolean stopOnErr; - private Integer parallelNum; - private Boolean parallelBuildOn; + // parallelization + private String parallelBuildCmd; + private Boolean isParallelBuildEnabled; + private Integer parallelNumberAttribute; // negative number denotes "optimal" value, see getOptimalParallelJobNum() + private boolean isTest; // Miscellaneous @@ -327,9 +330,10 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider stopOnErr = builder.stopOnErr; ignoreErrCmd = builder.ignoreErrCmd; + + isParallelBuildEnabled = builder.isParallelBuildEnabled; + parallelNumberAttribute = builder.parallelNumberAttribute; parallelBuildCmd = builder.parallelBuildCmd; - parallelNum = builder.parallelNum; - parallelBuildOn = builder.parallelBuildOn; if(builder.outputEntries != null){ outputEntries = builder.outputEntries.clone(); @@ -372,17 +376,15 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider } catch (CoreException e) { } } - if(getParallelizationNum() != builder.getParallelizationNum() - && supportsParallelBuild()){ + if (isParallelBuildOn() != builder.isParallelBuildOn() && supportsParallelBuild()) { try { - setParallelizationNum(builder.getParallelizationNum()); + setParallelBuildOn(builder.isParallelBuildOn()); } catch (CoreException e) { } } - if(isParallelBuildOn() != builder.isParallelBuildOn() - && supportsParallelBuild()){ + if (getParallelizationNumAttribute() != builder.getParallelizationNumAttribute() && supportsParallelBuild()) { try { - setParallelBuildOn(builder.isParallelBuildOn()); + setParallelizationNum(builder.getParallelizationNumAttribute()); } catch (CoreException e) { } } @@ -552,23 +554,23 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider ignoreErrCmd = SafeStringInterner.safeIntern(element.getAttribute(ATTRIBUTE_IGNORE_ERR_CMD)); - tmp = element.getAttribute(ATTRIBUTE_STOP_ON_ERR); - if(tmp != null) - stopOnErr = Boolean.valueOf(tmp); - - parallelBuildCmd = SafeStringInterner.safeIntern(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) - parallelBuildOn = Boolean.valueOf(tmp); - + tmp = element.getAttribute(ATTRIBUTE_STOP_ON_ERR); + if (tmp != null) + stopOnErr = Boolean.valueOf(tmp); + + tmp = element.getAttribute(ATTRIBUTE_PARALLEL_BUILD_CMD); + if (tmp != null) + 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 errorParserIds = SafeStringInterner.safeIntern(element.getAttribute(IToolChain.ERROR_PARSERS)); @@ -618,6 +620,43 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider 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 * specified in the argument @@ -748,24 +787,22 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider if(element.getAttribute(ATTRIBUTE_IGNORE_ERR_CMD) != null) ignoreErrCmd = SafeStringInterner.safeIntern(element.getAttribute(ATTRIBUTE_IGNORE_ERR_CMD)); - tmp = element.getAttribute(ATTRIBUTE_STOP_ON_ERR); - if(tmp != null) - stopOnErr = Boolean.valueOf(tmp); - - if(element.getAttribute(ATTRIBUTE_PARALLEL_BUILD_CMD) != null) - parallelBuildCmd = SafeStringInterner.safeIntern(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) - parallelBuildOn = Boolean.valueOf(tmp); + tmp = element.getAttribute(ATTRIBUTE_STOP_ON_ERR); + if (tmp != null) + stopOnErr = Boolean.valueOf(tmp); + + tmp = element.getAttribute(ATTRIBUTE_PARALLEL_BUILD_CMD); + if (tmp != null) + 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))); + } + } ICStorageElement[] children = element.getChildren(); for(int i = 0; i < children.length; i++){ @@ -869,16 +906,19 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider if(customBuildProperties != null) element.setAttribute(ATTRIBUTE_CUSTOM_PROPS, MapStorageElement.encodeMap(customBuildProperties)); - if(ignoreErrCmd != null) - element.setAttribute(ATTRIBUTE_IGNORE_ERR_CMD, ignoreErrCmd); - if(stopOnErr != null) - element.setAttribute(ATTRIBUTE_STOP_ON_ERR, stopOnErr.toString()); - if(parallelBuildCmd != null) - element.setAttribute(ATTRIBUTE_PARALLEL_BUILD_CMD, parallelBuildCmd); - if(parallelNum != null) - element.setAttribute(ATTRIBUTE_PARALLELIZATION_NUMBER, parallelNum.toString()); - if(parallelBuildOn != null) - element.setAttribute(ATTRIBUTE_PARALLEL_BUILD_ON, parallelBuildOn.toString()); + if (ignoreErrCmd != null) + element.setAttribute(ATTRIBUTE_IGNORE_ERR_CMD, ignoreErrCmd); + if (stopOnErr != null) + element.setAttribute(ATTRIBUTE_STOP_ON_ERR, stopOnErr.toString()); + + if (parallelBuildCmd != null) + element.setAttribute(ATTRIBUTE_PARALLEL_BUILD_CMD, parallelBuildCmd); + + 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 // an IConfigurationElement is needed to load it! if (buildFileGeneratorElement != null) { @@ -965,13 +1005,18 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider if(customBuildProperties != null) element.setAttribute(ATTRIBUTE_CUSTOM_PROPS, MapStorageElement.encodeMap(customBuildProperties)); - if(getIgnoreErrCmdAttribute() != null) - element.setAttribute(ATTRIBUTE_IGNORE_ERR_CMD, getIgnoreErrCmdAttribute()); - element.setAttribute(ATTRIBUTE_STOP_ON_ERR, Boolean.valueOf(isStopOnError()).toString()); - if(getParrallelBuildCmd() != null) - element.setAttribute(ATTRIBUTE_PARALLEL_BUILD_CMD, getParrallelBuildCmd()); - element.setAttribute(ATTRIBUTE_PARALLELIZATION_NUMBER, new Integer(getParallelizationNumAttribute()).toString()); - element.setAttribute(ATTRIBUTE_PARALLEL_BUILD_ON, Boolean.valueOf(isParallelBuildOn()).toString()); + if (getIgnoreErrCmdAttribute() != null) + element.setAttribute(ATTRIBUTE_IGNORE_ERR_CMD, getIgnoreErrCmdAttribute()); + element.setAttribute(ATTRIBUTE_STOP_ON_ERR, Boolean.valueOf(isStopOnError()).toString()); + + if (parallelBuildCmd != null) + element.setAttribute(ATTRIBUTE_PARALLEL_BUILD_CMD, parallelBuildCmd); + + 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 // an IConfigurationElement is needed to load it! if (buildFileGeneratorElement != null) { @@ -1042,16 +1087,17 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider public String getArguments() { String args = getArgumentsAttribute(); 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 reversedParallelBuildCmd = !isParallelBuildOn() ? getParallelizationCmd(getParallelizationNum()) : EMPTY_STRING; + String reversedParallelBuildCmd = !isParallelBuildOn() ? getParallelizationCmd(parallelNum) : EMPTY_STRING; args = removeCmd(args, reversedStopOnErrCmd); args = removeCmd(args, reversedParallelBuildCmd); args = addCmd(args, stopOnErrCmd); - args = addCmd(args, parallelBuildCmd); + args = addCmd(args, parallelCmd); return args != null ? args.trim() : null; } @@ -1114,18 +1160,27 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider return index; } - public String getParallelizationCmd(int num){ + public String getParallelizationCmd(int num) { String pattern = getParrallelBuildCmd(); - if(pattern.length() == 0){ - return EMPTY_STRING; - }if(num == 0){ + if (pattern.length() == 0 || num == 0) { return EMPTY_STRING; } - - return processParallelPattern(pattern, num < 0, num); + // "unlimited" number of jobs results in not adding the number to parallelization cmd + // 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: + *
  • Pattern 1 (supports "-j*"): "text*text" -> "text#text"
  • + *
  • Pattern 2 (supports "-[j*]"): "text[text*text]text" -> "texttext#texttext
  • + *
    Where # is num or empty if {@code empty} is {@code true}) + */ private String processParallelPattern(String pattern, boolean empty, int num){ + Assert.isTrue(num > 0); + int start = pattern.indexOf(PARALLEL_PATTERN_NUM_START); int end = -1; boolean hasStartChar = false; @@ -1238,10 +1293,10 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider if(newArgs != null){ 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, parallelBuildCmd); + newArgs = removeCmd(newArgs, parallelCmd); } setArgumentsAttribute(newArgs); } @@ -1915,7 +1970,6 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider return attr; } - public String getFullBuildTarget() { return getIncrementalBuildTarget(); @@ -2385,34 +2439,80 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider return false; } - public int getParallelizationNum() { - if(supportsParallelBuild()) - return getParallelizationNumAttribute(); - return 1; + /** + * Returns the optimal number of parallel jobs. + * The number is the number of available processors on the machine. + * + * The function never returns number smaller than 1. + */ + public int getOptimalParallelJobNum() { + return Runtime.getRuntime().availableProcessors(); } - public int getParallelizationNumAttribute(){ - if(parallelNum == null){ + /** + * 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: + *
    +	 *  Status       Returns
    +	 * No parallel      1       
    +	 * Optimal       -CPU# (negative number of processors) 
    +	 * Specific        >0  (positive number)
    +	 * Unlimited    Builder.UNLIMITED_JOBS
    +	 * 
    + */ + public int getParallelizationNumAttribute() { + if (!isParallelBuildOn()) + return 1; + + if(parallelNumberAttribute == null){ if(superClass != null){ return ((Builder)superClass).getParallelizationNumAttribute(); } return 1; } - return parallelNum.intValue(); + return parallelNumberAttribute.intValue(); } - public void setParallelizationNum(int num) throws CoreException { -// if(num == 0 || supportsParallelBuild()){ - Integer newParallelNum = new Integer(num); + private void setParallelizationNumAttribute(int parallelNumber) { + isParallelBuildEnabled = (parallelNumber != 1); + 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: + *
    - any number <=0 is interpreted as setting "optimal" property, + * the value of the number itself is ignored in this case + *
    - 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 args = getArgumentsAttribute(); String updatedArgs = removeCmd(args, curCmd); - if(!updatedArgs.equals(args)){ + if (!updatedArgs.equals(args)) { setArgumentsAttribute(updatedArgs); } - parallelNum = newParallelNum; + + setParallelizationNumAttribute(jobs); setDirty(true); -// } + } } public boolean supportsParallelBuild() { @@ -2446,10 +2546,10 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider return ignoreErrCmd; } - public String getParrallelBuildCmd(){ - if(parallelBuildCmd == null){ - if(superClass != null){ - return ((Builder)superClass).getParrallelBuildCmd(); + public String getParrallelBuildCmd() { + if (parallelBuildCmd == null) { + if (superClass != null) { + return ((Builder) superClass).getParrallelBuildCmd(); } return EMPTY_STRING; } @@ -2457,31 +2557,35 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider } public boolean isParallelBuildOn() { - if(parallelBuildOn == null){ - if(superClass != null){ + if (!supportsParallelBuild()) { + return false; + } + if (isParallelBuildEnabled == null) { + if (superClass != null) { return getSuperClass().isParallelBuildOn(); } return false; } - return parallelBuildOn.booleanValue(); + return isParallelBuildEnabled.booleanValue(); } - public void setParallelBuildOn(boolean on) throws CoreException{ - if(isParallelBuildOn() == on) - return; - if(on && !supportsParallelBuild()) - return; - - String curCmd = getParallelizationCmd(getParallelizationNum()); - String args = getArgumentsAttribute(); - String updatedArgs = removeCmd(args, curCmd); - if(!updatedArgs.equals(args)){ - setArgumentsAttribute(updatedArgs); + /** + * {@inheritDoc} + * + * @param on - the flag to enable or disable parallel mode. + *
    {@code true} to enable, in this case the maximum number of jobs + * will be set to "optimal" number, see {@link #getOptimalParallelJobNum()}. + *
    {@code false} to disable, the number of jobs will be set to 1. + */ + public void setParallelBuildOn(boolean on) throws CoreException { + if (on) { + // set "optimal" jobs by default when enabling parallel build + setParallelizationNum(-1); + } else { + setParallelizationNum(1); } - parallelBuildOn = Boolean.valueOf(on); - setDirty(true); } - + public Set contributeErrorParsers(Set set){ if(getErrorParserIds() != null){ if(set == null) @@ -2638,6 +2742,7 @@ public class Builder extends HoldsOptions implements IBuilder, IMatchKeyProvider public boolean isExtensionBuildObject() { return isExtensionElement(); } + @Override public String toString() { return getUniqueRealName(); 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 ef84a29dc1e..51f3c30812d 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 @@ -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 */ - /* (non-Javadoc) + /** * Initialize the configuration information from an element in the * manifest file or provided by a dynamicElementProvider * @@ -803,7 +803,7 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild isTest = Boolean.valueOf(tmp).booleanValue(); } - /* (non-Javadoc) + /** * Initialize the configuration information from the XML element * specified in the argument * @@ -874,8 +874,8 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild if (element.getAttribute(CLEAN_COMMAND) != null) { cleanCommand = SafeStringInterner.safeIntern(element.getAttribute(CLEAN_COMMAND)); } - - // Get the pre-build and post-build commands + + // Get the pre-build and post-build commands if (element.getAttribute(PREBUILD_STEP) != null) { prebuildStep = SafeStringInterner.safeIntern(element.getAttribute(PREBUILD_STEP)); } @@ -891,7 +891,7 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild if (element.getAttribute(POSTANNOUNCEBUILD_STEP) != null) { postannouncebuildStep = SafeStringInterner.safeIntern(element.getAttribute(POSTANNOUNCEBUILD_STEP)); - } + } } /** @@ -1568,7 +1568,7 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild /* (non-Javadoc) * @see org.eclipse.cdt.core.build.managed.IConfiguration#setPrebuildStep(java.lang.String) */ - public void setPrebuildStep(String step) { + public void setPrebuildStep(String step) { if (step == null && prebuildStep == null) return; if (prebuildStep == null || step == null || !prebuildStep.equals(step)) { prebuildStep = step; @@ -1577,11 +1577,10 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild } } - /* (non-Javadoc) * @see org.eclipse.cdt.core.build.managed.IConfiguration#setPostbuildStep(java.lang.String) */ - public void setPostbuildStep(String step) { + public void setPostbuildStep(String step) { if (step == null && postbuildStep == null) return; if (postbuildStep == null || step == null || !postbuildStep.equals(step)) { postbuildStep = step; @@ -1593,7 +1592,7 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild /* (non-Javadoc) * @see org.eclipse.cdt.core.build.managed.IConfiguration#setPreannouncebuildStep(java.lang.String) */ - public void setPreannouncebuildStep(String announceStep) { + public void setPreannouncebuildStep(String announceStep) { if (announceStep == null && preannouncebuildStep == null) return; if (preannouncebuildStep == null || announceStep == null || !preannouncebuildStep.equals(announceStep)) { preannouncebuildStep = announceStep; @@ -1605,7 +1604,7 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild /* (non-Javadoc) * @see org.eclipse.cdt.core.build.managed.IConfiguration#setPostannouncebuildStep(java.lang.String) */ - public void setPostannouncebuildStep(String announceStep) { + public void setPostannouncebuildStep(String announceStep) { if (announceStep == null && postannouncebuildStep == null) return; if (postannouncebuildStep == null || announceStep == null || !postannouncebuildStep.equals(announceStep)) { postannouncebuildStep = announceStep; @@ -1785,7 +1784,7 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild ((FolderInfo)getRootFolderInfo()).resetOptionSettings(); } - /* + /** * Create a resource configuration object for the passed-in file */ public IResourceConfiguration createResourceConfiguration(IFile file) @@ -1932,7 +1931,7 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild return getRootFolderInfo().getToolFromInputExtension(sourceExtension); } - /* + /** * 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 * 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; } */ - /* + /** * this method is used for enabling/disabling the internal builder * for the given configuration * @@ -2121,7 +2120,7 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild return null; } - /* + /** * returns whether the internal builder is enabled * @return boolean */ @@ -2129,7 +2128,7 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild return getBuilder().isInternalBuilder(); } - /* + /** * * sets the Internal Builder mode * @@ -2144,7 +2143,7 @@ public class Configuration extends BuildObject implements IConfiguration, IBuild } } - /* + /** * returns the Internal Builder mode * if true, internal builder will ignore build errors while building, * 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 - * * @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){ - if(getInternalBuilderParallel() == parallel) - return; - - try { - getEditableBuilder().setParallelBuildOn(parallel); - } catch (CoreException e) { - } + setParallelDef(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 + * + * @deprecated since CDT 9.0. Use {@link #getParallelDef()} */ + @Deprecated 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){ if(getParallelDef() == parallel) return; - int num = getParallelNumber(); - if(num != 0){ - setParallelNumber(-num); - } else { - if(parallel){ - setParallelNumber(-1); - } else { - setParallelNumber(1); - } + try { + getEditableBuilder().setParallelBuildOn(parallel); + } catch (CoreException e) { + ManagedBuilderCorePlugin.log(e); } } /** - * @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(){ - int num = getBuilder().getParallelizationNum(); - return num <= 0; + return getBuilder().isParallelBuildOn(); } /** - * sets number of Parallel threads + * Sets maximum number of parallel threads/jobs to be used by builder. + * + * @param jobs - maximum number of jobs or threads. For details how + * the number is interpreted see {@link Builder#setParallelizationNum(int)}. */ - public void setParallelNumber(int n){ + public void setParallelNumber(int jobs){ try { - getEditableBuilder().setParallelizationNum(n); + getEditableBuilder().setParallelizationNum(jobs); } catch (CoreException e) { + ManagedBuilderCorePlugin.log(e); } } /** - * returns number of Parallel threads + * Returns maximum number of parallel threads/jobs used by the configuration's builder. + * @see #setParallelDef(boolean) * - * @return int + * @return - maximum number of parallel threads or jobs used by the builder. */ public int getParallelNumber(){ return getBuilder().getParallelizationNum(); 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 4acd71aeba6..31d37860f8e 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 @@ -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 * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -906,244 +906,242 @@ public class GeneratedMakefileBuilder extends ACBuilder { } IPath makeCommand = new Path(makeCmd); - if (makeCommand != null) { - String[] msgs = new String[2]; - msgs[0] = makeCommand.toString(); - msgs[1] = currentProject.getName(); - monitor.subTask(ManagedMakeMessages.getFormattedString(MAKE, msgs)); + String[] msgs = new String[2]; + msgs[0] = makeCommand.toString(); + msgs[1] = currentProject.getName(); + monitor.subTask(ManagedMakeMessages.getFormattedString(MAKE, msgs)); - // Get a build console for the project - StringBuffer buf = new StringBuffer(); - IConsole console = CCorePlugin.getDefault().getConsole(); - console.start(currentProject); - ConsoleOutputStream consoleOutStream = console.getOutputStream(); - String[] consoleHeader = new String[3]; + // Get a build console for the project + StringBuffer buf = new StringBuffer(); + IConsole console = CCorePlugin.getDefault().getConsole(); + console.start(currentProject); + ConsoleOutputStream consoleOutStream = console.getOutputStream(); + String[] consoleHeader = new String[3]; + switch (buildType) { + case FULL_BUILD: + case INCREMENTAL_BUILD: + consoleHeader[0] = ManagedMakeMessages.getResourceString(TYPE_INC); + break; + case CLEAN_BUILD: + consoleHeader[0] = ManagedMakeMessages.getResourceString(TYPE_CLEAN); + break; + } + + consoleHeader[1] = info.getConfigurationName(); + consoleHeader[2] = currentProject.getName(); + buf.append(NEWLINE); + buf.append(ManagedMakeMessages.getFormattedString(CONSOLE_HEADER, consoleHeader)).append(NEWLINE); + buf.append(NEWLINE); + + IConfiguration cfg = info.getDefaultConfiguration(); + if(!cfg.isSupported()){ + String msg = ManagedMakeMessages.getFormattedString(WARNING_UNSUPPORTED_CONFIGURATION,new String[] {cfg.getName(),cfg.getToolChain().getName()}); + buf.append(msg).append(NEWLINE); + buf.append(NEWLINE); + } + consoleOutStream.write(buf.toString().getBytes()); + consoleOutStream.flush(); + + // Remove all markers for this project + removeAllMarkers(currentProject); + + // Get a launcher for the make command + String errMsg = null; + IBuilder builder = info.getDefaultConfiguration().getBuilder(); + ICommandLauncher launcher = builder.getCommandLauncher(); + launcher.setProject(currentProject); + launcher.showCommand(true); + + // Set the environmennt + IBuildEnvironmentVariable variables[] = ManagedBuildManager.getEnvironmentVariableProvider().getVariables(cfg,true,true); + String[] env = null; + ArrayList envList = new ArrayList(); + if (variables != null) { + for(int i = 0; i < variables.length; i++){ + envList.add(variables[i].getName() + "=" + variables[i].getValue()); //$NON-NLS-1$ + } + env = envList.toArray(new String[envList.size()]); + } + + // Hook up an error parser manager + String[] errorParsers = info.getDefaultConfiguration().getErrorParserList(); + ErrorParserManager epm = new ErrorParserManager(getProject(), workingDirectoryURI, this, errorParsers); + epm.setOutputStream(consoleOutStream); + // This variable is necessary to ensure that the EPM stream stay open + // until we explicitly close it. See bug#123302. + OutputStream epmOutputStream = epm.getOutputStream(); + + // Get the arguments to be passed to make from build model + ArrayList makeArgs = new ArrayList(); + String arg = info.getBuildArguments(); + if (arg.length() > 0) { + String[] args = arg.split("\\s"); //$NON-NLS-1$ + for (int i = 0; i < args.length; ++i) { + makeArgs.add(args[i]); + } + } + + String[] makeTargets; + String prebuildStep = info.getPrebuildStep(); + //try to resolve the build macros in the prebuildStep + try{ + prebuildStep = ManagedBuildManager.getBuildMacroProvider().resolveValueToMakefileFormat( + prebuildStep, + "", //$NON-NLS-1$ + " ", //$NON-NLS-1$ + IBuildMacroProvider.CONTEXT_CONFIGURATION, + cfg); + } catch (BuildMacroException e){ + } + boolean prebuildStepPresent = (prebuildStep.length() > 0); + Process proc = null; + boolean isuptodate = false; + + if (prebuildStepPresent) { + @SuppressWarnings("unchecked") + ArrayList premakeArgs = (ArrayList) makeArgs.clone(); + String[] premakeTargets; switch (buildType) { - case FULL_BUILD: - case INCREMENTAL_BUILD: - consoleHeader[0] = ManagedMakeMessages.getResourceString(TYPE_INC); - break; - case CLEAN_BUILD: - consoleHeader[0] = ManagedMakeMessages.getResourceString(TYPE_CLEAN); - break; - } - - consoleHeader[1] = info.getConfigurationName(); - consoleHeader[2] = currentProject.getName(); - buf.append(NEWLINE); - buf.append(ManagedMakeMessages.getFormattedString(CONSOLE_HEADER, consoleHeader)).append(NEWLINE); - buf.append(NEWLINE); - - IConfiguration cfg = info.getDefaultConfiguration(); - if(!cfg.isSupported()){ - String msg = ManagedMakeMessages.getFormattedString(WARNING_UNSUPPORTED_CONFIGURATION,new String[] {cfg.getName(),cfg.getToolChain().getName()}); - buf.append(msg).append(NEWLINE); - buf.append(NEWLINE); - } - consoleOutStream.write(buf.toString().getBytes()); - consoleOutStream.flush(); - - // Remove all markers for this project - removeAllMarkers(currentProject); - - // Get a launcher for the make command - String errMsg = null; - IBuilder builder = info.getDefaultConfiguration().getBuilder(); - ICommandLauncher launcher = builder.getCommandLauncher(); - launcher.setProject(currentProject); - launcher.showCommand(true); - - // Set the environmennt - IBuildEnvironmentVariable variables[] = ManagedBuildManager.getEnvironmentVariableProvider().getVariables(cfg,true,true); - String[] env = null; - ArrayList envList = new ArrayList(); - if (variables != null) { - for(int i = 0; i < variables.length; i++){ - envList.add(variables[i].getName() + "=" + variables[i].getValue()); //$NON-NLS-1$ - } - env = envList.toArray(new String[envList.size()]); - } - - // Hook up an error parser manager - String[] errorParsers = info.getDefaultConfiguration().getErrorParserList(); - ErrorParserManager epm = new ErrorParserManager(getProject(), workingDirectoryURI, this, errorParsers); - epm.setOutputStream(consoleOutStream); - // This variable is necessary to ensure that the EPM stream stay open - // until we explicitly close it. See bug#123302. - OutputStream epmOutputStream = epm.getOutputStream(); - - // Get the arguments to be passed to make from build model - ArrayList makeArgs = new ArrayList(); - String arg = info.getBuildArguments(); - if (arg.length() > 0) { - String[] args = arg.split("\\s"); //$NON-NLS-1$ - for (int i = 0; i < args.length; ++i) { - makeArgs.add(args[i]); - } - } - - String[] makeTargets; - String prebuildStep = info.getPrebuildStep(); - //try to resolve the build macros in the prebuildStep - try{ - prebuildStep = ManagedBuildManager.getBuildMacroProvider().resolveValueToMakefileFormat( - prebuildStep, - "", //$NON-NLS-1$ - " ", //$NON-NLS-1$ - IBuildMacroProvider.CONTEXT_CONFIGURATION, - cfg); - } catch (BuildMacroException e){ - } - boolean prebuildStepPresent = (prebuildStep.length() > 0); - Process proc = null; - boolean isuptodate = false; - - if (prebuildStepPresent) { - @SuppressWarnings("unchecked") - ArrayList premakeArgs = (ArrayList) makeArgs.clone(); - String[] premakeTargets; - switch (buildType) { - case INCREMENTAL_BUILD: { - // For an incremental build with a prebuild step: - // Check the status of the main build with "make -q main-build" - // If up to date: - // then: don't invoke the prebuild step, which should be run only if - // something needs to be built in the main build - // else: invoke the prebuild step and the main build step - premakeArgs.add("-q"); //$NON-NLS-1$ - premakeArgs.add("main-build"); //$NON-NLS-1$ - premakeTargets = premakeArgs.toArray(new String[premakeArgs.size()]); - proc = launcher.execute(makeCommand, premakeTargets, env, workingDirectory, monitor); - if (proc != null) { - try { - // Close the input of the process since we will never write to it - proc.getOutputStream().close(); - } catch (IOException e) { - } - if (launcher.waitAndRead(epm.getOutputStream(), epm.getOutputStream(), - new SubProgressMonitor(monitor, - IProgressMonitor.UNKNOWN)) != ICommandLauncher.OK) { - errMsg = launcher.getErrorMessage(); - } - } else { - errMsg = launcher.getErrorMessage(); - } - - if ((errMsg != null && errMsg.length() > 0) || proc == null) { - // Can't tell if the build is needed, so assume it is, and let any errors be triggered - // when the "real" build is invoked below - makeArgs.add("pre-build"); //$NON-NLS-1$ - makeArgs.add("main-build"); //$NON-NLS-1$ - } else { - // The "make -q" command launch was successful - if (proc.exitValue() == 0) { - // If the status value returned from "make -q" is 0, then the build state is up-to-date - isuptodate = true; - // Report that the build was up to date, and thus nothing needs to be built - String uptodateMsg = ManagedMakeMessages.getFormattedString(NOTHING_BUILT, currentProject.getName()); - buf = new StringBuffer(); - buf.append(NEWLINE); - buf.append(uptodateMsg).append(NEWLINE); - // Write message on the console - consoleOutStream.write(buf.toString().getBytes()); - consoleOutStream.flush(); - epmOutputStream.close(); - consoleOutStream.close(); - } else { - // The status value was other than 0, so press on with the build process - makeArgs.add("pre-build"); //$NON-NLS-1$ - makeArgs.add("main-build"); //$NON-NLS-1$ - } - } - break; - } - case FULL_BUILD: { -// makeArgs.add("clean"); //$NON-NLS-1$ - makeArgs.add("pre-build"); //$NON-NLS-1$ - makeArgs.add("main-build"); //$NON-NLS-1$ - break; - } - case CLEAN_BUILD: { - makeArgs.add("clean"); //$NON-NLS-1$ - break; - } - } - - } else { - // No prebuild step - // - makeArgs.addAll(Arrays.asList(getMakeTargets(buildType))); - } - - makeTargets = makeArgs.toArray(new String[makeArgs.size()]); - - // Launch make - main invocation - if (!isuptodate) { - proc = launcher.execute(makeCommand, makeTargets, env, workingDirectory, monitor); + case INCREMENTAL_BUILD: { + // For an incremental build with a prebuild step: + // Check the status of the main build with "make -q main-build" + // If up to date: + // then: don't invoke the prebuild step, which should be run only if + // something needs to be built in the main build + // else: invoke the prebuild step and the main build step + premakeArgs.add("-q"); //$NON-NLS-1$ + premakeArgs.add("main-build"); //$NON-NLS-1$ + premakeTargets = premakeArgs.toArray(new String[premakeArgs.size()]); + proc = launcher.execute(makeCommand, premakeTargets, env, workingDirectory, monitor); if (proc != null) { try { // Close the input of the process since we will never write to it proc.getOutputStream().close(); } catch (IOException e) { } - - int state = launcher.waitAndRead(epm.getOutputStream(), epm.getOutputStream(), + if (launcher.waitAndRead(epm.getOutputStream(), epm.getOutputStream(), new SubProgressMonitor(monitor, - IProgressMonitor.UNKNOWN)); - if(state != ICommandLauncher.OK){ + IProgressMonitor.UNKNOWN)) != ICommandLauncher.OK) { errMsg = launcher.getErrorMessage(); - - if(state == ICommandLauncher.COMMAND_CANCELED){ - //TODO: the better way of handling cancel is needed - //currently the rebuild state is set to true forcing the full rebuild - //on the next builder invocation - info.getDefaultConfiguration().setRebuildState(true); - } - } - - // Force a resync of the projects without allowing the user to cancel. - // This is probably unkind, but short of this there is no way to insure - // the UI is up-to-date with the build results - monitor.subTask(ManagedMakeMessages - .getResourceString(REFRESH)); - try { - //currentProject.refreshLocal(IResource.DEPTH_INFINITE, null); - - // use the refresh scope manager to refresh - RefreshScopeManager refreshManager = RefreshScopeManager.getInstance(); - IWorkspaceRunnable runnable = refreshManager.getRefreshRunnable(currentProject); - ResourcesPlugin.getWorkspace().run(runnable, null, IWorkspace.AVOID_UPDATE, null); - } catch (CoreException e) { - monitor.subTask(ManagedMakeMessages - .getResourceString(REFRESH_ERROR)); } } else { errMsg = launcher.getErrorMessage(); } - // Report either the success or failure of our mission - buf = new StringBuffer(); - if (errMsg != null && errMsg.length() > 0) { - String errorDesc = ManagedMakeMessages.getResourceString(BUILD_ERROR); - buf.append(errorDesc).append(NEWLINE); - buf.append("(").append(errMsg).append(")"); //$NON-NLS-1$ //$NON-NLS-2$ + if ((errMsg != null && errMsg.length() > 0) || proc == null) { + // Can't tell if the build is needed, so assume it is, and let any errors be triggered + // when the "real" build is invoked below + makeArgs.add("pre-build"); //$NON-NLS-1$ + makeArgs.add("main-build"); //$NON-NLS-1$ } else { - // Report a successful build - String successMsg = ManagedMakeMessages.getFormattedString(BUILD_FINISHED, - currentProject.getName()); - buf.append(successMsg).append(NEWLINE); + // The "make -q" command launch was successful + if (proc.exitValue() == 0) { + // If the status value returned from "make -q" is 0, then the build state is up-to-date + isuptodate = true; + // Report that the build was up to date, and thus nothing needs to be built + String uptodateMsg = ManagedMakeMessages.getFormattedString(NOTHING_BUILT, currentProject.getName()); + buf = new StringBuffer(); + buf.append(NEWLINE); + buf.append(uptodateMsg).append(NEWLINE); + // Write message on the console + consoleOutStream.write(buf.toString().getBytes()); + consoleOutStream.flush(); + epmOutputStream.close(); + consoleOutStream.close(); + } else { + // The status value was other than 0, so press on with the build process + makeArgs.add("pre-build"); //$NON-NLS-1$ + makeArgs.add("main-build"); //$NON-NLS-1$ + } + } + break; + } + case FULL_BUILD: { +// makeArgs.add("clean"); //$NON-NLS-1$ + makeArgs.add("pre-build"); //$NON-NLS-1$ + makeArgs.add("main-build"); //$NON-NLS-1$ + break; + } + case CLEAN_BUILD: { + makeArgs.add("clean"); //$NON-NLS-1$ + break; + } + } + + } else { + // No prebuild step + // + makeArgs.addAll(Arrays.asList(getMakeTargets(buildType))); + } + + makeTargets = makeArgs.toArray(new String[makeArgs.size()]); + + // Launch make - main invocation + if (!isuptodate) { + proc = launcher.execute(makeCommand, makeTargets, env, workingDirectory, monitor); + if (proc != null) { + try { + // Close the input of the process since we will never write to it + proc.getOutputStream().close(); + } catch (IOException e) { } - // Write message on the console - consoleOutStream.write(buf.toString().getBytes()); - consoleOutStream.flush(); - epmOutputStream.close(); + int state = launcher.waitAndRead(epm.getOutputStream(), epm.getOutputStream(), + new SubProgressMonitor(monitor, + IProgressMonitor.UNKNOWN)); + if(state != ICommandLauncher.OK){ + errMsg = launcher.getErrorMessage(); + + if(state == ICommandLauncher.COMMAND_CANCELED){ + //TODO: the better way of handling cancel is needed + //currently the rebuild state is set to true forcing the full rebuild + //on the next builder invocation + info.getDefaultConfiguration().setRebuildState(true); + } + } - // Generate any error markers that the build has discovered - monitor.subTask(ManagedMakeMessages.getResourceString(MARKERS)); - addBuilderMarkers(epm); - consoleOutStream.close(); + // Force a resync of the projects without allowing the user to cancel. + // This is probably unkind, but short of this there is no way to insure + // the UI is up-to-date with the build results + monitor.subTask(ManagedMakeMessages + .getResourceString(REFRESH)); + try { + //currentProject.refreshLocal(IResource.DEPTH_INFINITE, null); + + // use the refresh scope manager to refresh + RefreshScopeManager refreshManager = RefreshScopeManager.getInstance(); + IWorkspaceRunnable runnable = refreshManager.getRefreshRunnable(currentProject); + ResourcesPlugin.getWorkspace().run(runnable, null, IWorkspace.AVOID_UPDATE, null); + } catch (CoreException e) { + monitor.subTask(ManagedMakeMessages + .getResourceString(REFRESH_ERROR)); + } + } else { + errMsg = launcher.getErrorMessage(); } + + // Report either the success or failure of our mission + buf = new StringBuffer(); + if (errMsg != null && errMsg.length() > 0) { + String errorDesc = ManagedMakeMessages.getResourceString(BUILD_ERROR); + buf.append(errorDesc).append(NEWLINE); + buf.append("(").append(errMsg).append(")"); //$NON-NLS-1$ //$NON-NLS-2$ + } else { + // Report a successful build + String successMsg = ManagedMakeMessages.getFormattedString(BUILD_FINISHED, + currentProject.getName()); + buf.append(successMsg).append(NEWLINE); + } + + // Write message on the console + consoleOutStream.write(buf.toString().getBytes()); + consoleOutStream.flush(); + epmOutputStream.close(); + + // Generate any error markers that the build has discovered + monitor.subTask(ManagedMakeMessages.getResourceString(MARKERS)); + addBuilderMarkers(epm); + consoleOutStream.close(); } } catch (Exception e) { forgetLastBuiltState(); @@ -1196,7 +1194,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { boolean resumeOnErr, 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 IProject currentProject = cfg.getOwner().getProject(); diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/MultiConfiguration.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/MultiConfiguration.java index d9834448cad..bfb3184d658 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/MultiConfiguration.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/MultiConfiguration.java @@ -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 * are made available under the terms of the Eclipse Public License v1.0 * 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.core.resources.IFile; import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.osgi.framework.Version; @@ -253,15 +254,23 @@ public class MultiConfiguration extends MultiItemsHolder implements 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() { - String s = fCfgs[0].getBuildArguments(); - for (int i=1; i