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