1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-08 08:45:44 +02:00

Patch for Sean Evoy:

- More data types for build model
- New natures for managed build
This commit is contained in:
Doug Schaefer 2003-05-29 14:01:04 +00:00
parent c09a240262
commit 6fa98d379b
16 changed files with 842 additions and 159 deletions

View file

@ -12,9 +12,6 @@ package org.eclipse.cdt.core.build.managed;
import org.eclipse.core.resources.IResource;
/**
*
*/
public interface IConfiguration extends IBuildObject {
/**
@ -38,17 +35,29 @@ public interface IConfiguration extends IBuildObject {
public ITool[] getTools();
/**
* Sets an option value for this configuration.
* Sets the value of a boolean option for this configuration.
*
* @param option
* @param value
* @param option The option to change.
* @param value The value to apply to the option.
* @throws BuildException
*/
public void setOption(IOption option, boolean value)
throws BuildException;
/**
* Sets the value of a string option for this configuration.
*
* @param option The option that will be effected by change.
* @param value The value to apply to the option.
*/
public void setOption(IOption option, String value)
throws BuildException;
/**
* Sets an option value for this configuration.
* @param option
* Sets the value of a list option for this configuration.
*
* @param option The option to change.
* @param value The values to apply to the option.
*/
public void setOption(IOption option, String[] value)
throws BuildException;

View file

@ -48,13 +48,6 @@ public interface IOption extends IBuildObject {
*/
public String getCommand();
/**
* @return a <code>String</code> containing the default value for the
* enumerated option.
*/
public String getDefaultEnumName ();
/**
* @return <code>String</code> containing the command associated with the
* enumeration name.
@ -75,6 +68,16 @@ public interface IOption extends IBuildObject {
*/
public String [] getStringListValue() throws BuildException;
/**
* @return a <code>String</code> containing the selected enumeration in an
* enumerated option. For an option that has not been changed by the user,
* the receiver will answer with the default defined in the plugin manifest.
* If the user has modified the selection, the receiver will answer with the
* overridden selection.
*/
public String getSelectedEnum ();
/**
* Returns the current value for this option if it is a String
*

View file

@ -31,6 +31,11 @@ public interface ITarget extends IBuildObject {
*/
public IResource getOwner();
/**
* @return the <code>ITarget</code> that is the parent of the receiver.
*/
public ITarget getParent();
/**
* Returns the list of platform specific tools associated with this
* platform.

View file

@ -90,6 +90,16 @@ public class ManagedBuildManager {
return targets;
}
/**
* @return
*/
public static Map getExtensionTargetMap() {
if (extensionTargetMap == null) {
extensionTargetMap = new HashMap();
}
return extensionTargetMap;
}
/**
* Returns the targets owned by this project. If none are owned,
* an empty array is returned.
@ -108,6 +118,7 @@ public class ManagedBuildManager {
}
}
public static ITarget getTarget(IResource resource, String id) {
if (resource != null) {
ResourceBuildInfo buildInfo = getBuildInfo(resource);
@ -115,7 +126,7 @@ public class ManagedBuildManager {
return buildInfo.getTarget(id);
}
ITarget target = (ITarget)extensionTargetMap.get(id);
ITarget target = (ITarget)getExtensionTargetMap().get(id);
if (target != null)
return target;
@ -158,23 +169,48 @@ public class ManagedBuildManager {
/**
* Set the string value for an option for a given config.
*
* @param config
* @param option
* @param value
* @param config The configuration the option belongs to.
* @param option The option to set the value for.
* @param value The boolean that the option should contain after the change.
*/
public static void setOption(IConfiguration config, IOption option, boolean value) {
try {
config.setOption(option, value);
} catch (BuildException e) {
return;
}
}
/**
* Set the string value for an option for a given config.
*
* @param config The configuration the option belongs to.
* @param option The option to set the value for.
* @param value The value that the option should contain after the change.
*/
public static void setOption(IConfiguration config, IOption option, String value) {
try {
config.setOption(option, value);
} catch (BuildException e) {
return;
}
}
/**
* Set the string array value for an option for a given config.
*
* @param config
* @param option
* @param value
* @param config The configuration the option belongs to.
* @param option The option to set the value for.
* @param value The values the option should contain after the change.
*/
public static void setOption(IConfiguration config, IOption option, String[] value) {
try {
config.setOption(option, value);
} catch (BuildException e) {
return;
}
}
/**
* Saves the build information associated with a project and all resources
* in the project to the build info file.
@ -229,11 +265,10 @@ public class ManagedBuildManager {
public static void addExtensionTarget(Target target) {
if (extensionTargets == null) {
extensionTargets = new ArrayList();
extensionTargetMap = new HashMap();
}
extensionTargets.add(target);
extensionTargetMap.put(target.getId(), target);
getExtensionTargetMap().put(target.getId(), target);
}
private static void loadExtensions() {
@ -279,6 +314,8 @@ public class ManagedBuildManager {
}
public static ResourceBuildInfo getBuildInfo(IResource resource, boolean create) {
// Make sure the extension information is loaded first
loadExtensions();
ResourceBuildInfo buildInfo = null;
try {
buildInfo = (ResourceBuildInfo)resource.getSessionProperty(buildInfoProperty);
@ -304,4 +341,6 @@ public class ManagedBuildManager {
public static ResourceBuildInfo getBuildInfo(IResource resource) {
return getBuildInfo(resource, false);
}
}

View file

@ -11,6 +11,7 @@
package org.eclipse.cdt.internal.core.build.managed;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.cdt.core.build.managed.BuildException;
@ -36,6 +37,7 @@ public class Configuration extends BuildObject implements IConfiguration {
/**
* A fresh new configuration for a target.
*
* @param target
* @param id
*/
@ -46,14 +48,28 @@ public class Configuration extends BuildObject implements IConfiguration {
target.addConfiguration(this);
}
/**
* Create a new configuration based on one already defined.
*
* @param target The <code>Target</code> the receiver will be added to.
* @param parent The <code>IConfiguration</code> to copy the settings from.
* @param id A unique ID for the configuration.
*/
public Configuration(Target target, IConfiguration parent, String id) {
this.id = id;
this.name = parent.getName();
this.target = target;
this.parent = parent;
target.addConfiguration(this);
}
/**
* Create a new <code>Configuration</code> based on the specification in the plugin manifest.
*
* @param target The <code>Target</code> the receiver will be added to.
* @param element The element from the manifest that contains the default configuration settings.
*/
public Configuration(Target target, IConfigurationElement element) {
this.target = target;
@ -75,6 +91,12 @@ public class Configuration extends BuildObject implements IConfiguration {
}
}
/**
* Build a configuration from the project manifest file.
*
* @param target The <code>Target</code> the configuration belongs to.
* @param element The element from the manifest that contains the overridden configuration information.
*/
public Configuration(Target target, Element element) {
this.target = target;
@ -88,8 +110,17 @@ public class Configuration extends BuildObject implements IConfiguration {
if (element.hasAttribute("name"))
setName(element.getAttribute("name"));
if (element.hasAttribute("parent"))
parent = target.getParent().getConfiguration(element.getAttribute("parent"));
if (element.hasAttribute("parent")) {
// See if the target has a parent
ITarget targetParent = target.getParent();
// If so, then get my parent from it
if (targetParent != null) {
parent = targetParent.getConfiguration(element.getAttribute("parent"));
}
else {
parent = null;
}
}
NodeList configElements = element.getChildNodes();
for (int i = 0; i < configElements.getLength(); ++i) {
@ -101,7 +132,13 @@ public class Configuration extends BuildObject implements IConfiguration {
}
public void serealize(Document doc, Element element) {
/**
* Persist receiver to project file.
*
* @param doc
* @param element
*/
public void serialize(Document doc, Element element) {
element.setAttribute("id", id);
if (name != null)
@ -115,7 +152,7 @@ public class Configuration extends BuildObject implements IConfiguration {
ToolReference toolRef = (ToolReference)toolReferences.get(i);
Element toolRefElement = doc.createElement("toolRef");
element.appendChild(toolRefElement);
toolRef.serealize(doc, toolRefElement);
toolRef.serialize(doc, toolRefElement);
}
}
@ -205,10 +242,28 @@ public class Configuration extends BuildObject implements IConfiguration {
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.build.managed.IConfiguration#setOption(org.eclipse.cdt.core.build.managed.IOption, boolean)
*/
public void setOption(IOption option, boolean value) throws BuildException {
// Is there a delta
if (option.getBooleanValue() != value)
createOptionReference(option).setValue(value);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.build.managed.IConfiguration#setOption(org.eclipse.cdt.core.build.managed.IOption, java.lang.String)
*/
public void setOption(IOption option, String value) throws BuildException {
String oldValue;
// Check whether this is an enumerated option
if (option.getValueType() == IOption.ENUMERATED) {
oldValue = option.getEnumCommand(option.getSelectedEnum());
}
else {
oldValue = option.getStringValue();
}
if (!oldValue.equals(value))
createOptionReference(option).setValue(value);
}
@ -216,7 +271,9 @@ public class Configuration extends BuildObject implements IConfiguration {
* @see org.eclipse.cdt.core.build.managed.IConfiguration#setOption(org.eclipse.cdt.core.build.managed.IOption, java.lang.String[])
*/
public void setOption(IOption option, String[] value) throws BuildException {
// Is there a delta
String[] oldValue = option.getStringListValue();
if(!Arrays.equals(value, oldValue))
createOptionReference(option).setValue(value);
}
}

View file

@ -37,6 +37,7 @@ public class Option extends BuildObject implements IOption {
private String command;
private static final String[] emptyStrings = new String[0];
private static final String EMPTY_STRING = new String();
public Option(ITool tool) {
this.tool = tool;
@ -64,7 +65,9 @@ public class Option extends BuildObject implements IOption {
// valueType
String valueTypeStr = element.getAttribute("valueType");
if (valueTypeStr == null || valueTypeStr.equals("string"))
if (valueTypeStr == null)
valueType = -1;
else if (valueTypeStr.equals("string"))
valueType = IOption.STRING;
else if (valueTypeStr.equals("stringList"))
valueType = IOption.STRING_LIST;
@ -107,6 +110,8 @@ public class Option extends BuildObject implements IOption {
}
value = valueList;
break;
default :
break;
}
}
@ -139,18 +144,19 @@ public class Option extends BuildObject implements IOption {
return command;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.build.managed.IOption#getDefaultEnumValue()
*/
public String getDefaultEnumName() {
return defaultEnumName;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.build.managed.IOption#getEnumCommand(java.lang.String)
*/
public String getEnumCommand(String name) {
return (String) enumCommands.get(name);
String cmd = (String) enumCommands.get(name);
return (cmd == null ? new String() : cmd);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.build.managed.IOption#getDefaultEnumValue()
*/
public String getSelectedEnum() {
return defaultEnumName;
}
/* (non-Javadoc)
@ -167,7 +173,8 @@ public class Option extends BuildObject implements IOption {
* @see org.eclipse.cdt.core.build.managed.IOption#getStringValue()
*/
public String getStringValue() {
return (String)value;
String v = (String) value;
return value == null ? EMPTY_STRING : v;
}
/* (non-Javadoc)

View file

@ -11,10 +11,9 @@
package org.eclipse.cdt.internal.core.build.managed;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.ListIterator;
import org.eclipse.cdt.core.build.managed.BuildException;
import org.eclipse.cdt.core.build.managed.IOption;
@ -23,6 +22,7 @@ import org.eclipse.cdt.core.build.managed.ITool;
import org.eclipse.core.runtime.IConfigurationElement;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
@ -33,9 +33,7 @@ public class OptionReference implements IOption {
private IOption option;
private ToolReference owner;
private Object value;
private String defaultEnumName;
private String command;
private Map enumCommands;
/**
* Created internally.
@ -46,7 +44,7 @@ public class OptionReference implements IOption {
public OptionReference(ToolReference owner, IOption option) {
this.owner = owner;
this.option = option;
// Until the option reference is changed, all values will be extracted from original option
owner.addOptionReference(this);
}
@ -63,7 +61,6 @@ public class OptionReference implements IOption {
owner.addOptionReference(this);
// value
enumCommands = new HashMap();
switch (option.getValueType()) {
case IOption.BOOLEAN:
value = new Boolean(element.getAttribute("defaultValue"));
@ -72,19 +69,7 @@ public class OptionReference implements IOption {
value = element.getAttribute("defaultValue");
break;
case IOption.ENUMERATED:
List enumList = new ArrayList();
IConfigurationElement[] enumElements = element.getChildren("optionEnum");
for (int i = 0; i < enumElements.length; ++i) {
String optName = enumElements[i].getAttribute("name");
String optCommand = enumElements[i].getAttribute("command");
enumList.add(optName);
enumCommands.put(optName, optCommand);
Boolean isDefault = new Boolean(enumElements[i].getAttribute("isDefault"));
if (isDefault.booleanValue()) {
defaultEnumName = optName;
}
}
value = enumList;
value = option.getEnumCommand(option.getSelectedEnum());
break;
case IOption.STRING_LIST:
List valueList = new ArrayList();
@ -112,14 +97,20 @@ public class OptionReference implements IOption {
// value
switch (option.getValueType()) {
case IOption.BOOLEAN:
value = new Boolean(element.getAttribute("value"));
break;
case IOption.STRING:
value = element.getAttribute("value");
case IOption.ENUMERATED:
value = (String) element.getAttribute("value");
break;
case IOption.STRING_LIST:
List valueList = new ArrayList();
NodeList nodes = element.getElementsByTagName("optionValue");
for (int i = 0; i < nodes.getLength(); ++i) {
valueList.add(((Element)nodes.item(i)).getAttribute("value"));
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
valueList.add(((Element)node).getAttribute("value"));
}
}
value = valueList;
break;
@ -128,33 +119,29 @@ public class OptionReference implements IOption {
}
/**
* Write out to project file.
* Persist receiver to project file.
*
* @param doc
* @param element
*/
public void serealize(Document doc, Element element) {
public void serialize(Document doc, Element element) {
element.setAttribute("id", option.getId());
// value
switch (option.getValueType()) {
case IOption.BOOLEAN:
element.setAttribute("value", ((Boolean)value).toString());
break;
case IOption.STRING:
case IOption.ENUMERATED:
element.setAttribute("value", (String)value);
break;
case IOption.STRING_LIST:
List stringList = (List)value;
for (int i = 0; i < stringList.size(); ++i) {
ArrayList stringList = (ArrayList)value;
ListIterator iter = stringList.listIterator();
while (iter.hasNext()) {
Element valueElement = doc.createElement("optionValue");
valueElement.setAttribute("value", (String)stringList.get(i));
element.appendChild(valueElement);
}
break;
case IOption.ENUMERATED:
List enumList = (List)value;
for (int i = 0; i < enumList.size(); ++i) {
Element valueElement = doc.createElement("optionEnum");
valueElement.setAttribute("value", (String)enumList.get(i));
valueElement.setAttribute("value", (String)iter.next());
element.appendChild(valueElement);
}
break;
@ -182,26 +169,11 @@ public class OptionReference implements IOption {
return option.getCommand();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.build.managed.IOption#getDefaultEnumValue()
*/
public String getDefaultEnumName() {
if (value == null) {
return option.getDefaultEnumName();
} else {
return defaultEnumName;
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.build.managed.IOption#getEnumCommand(java.lang.String)
*/
public String getEnumCommand(String name) {
if (value == null) {
return option.getEnumCommand(name);
} else {
return (String)enumCommands.get(name);
}
}
/* (non-Javadoc)
@ -233,14 +205,29 @@ public class OptionReference implements IOption {
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.build.managed.IOption#getDefaultEnumValue()
*/
public String getSelectedEnum() {
if (value == null) {
// Return the default defined for the enumeration in the manifest.
return option.getSelectedEnum();
} else {
// Value will contain the selection of the user
return (String) value;
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.build.managed.IOption#getStringListValue()
*/
public String[] getStringListValue() throws BuildException {
if (value == null)
return option.getStringListValue();
else if (getValueType() == IOption.STRING_LIST)
return (String[])value;
else if (getValueType() == IOption.STRING_LIST) {
ArrayList list = (ArrayList)value;
return (String[]) list.toArray(new String[list.size()]);
}
else
throw new BuildException("bad value type");
}
@ -287,16 +274,34 @@ public class OptionReference implements IOption {
return option.equals(target);
}
/**
* @param value
*/
public void setValue(boolean value) throws BuildException {
if (getValueType() == IOption.BOOLEAN)
this.value = new Boolean(value);
else
throw new BuildException("bad value type");
}
public void setValue(String value) throws BuildException {
if (getValueType() == IOption.STRING)
if (getValueType() == IOption.STRING || getValueType() == IOption.ENUMERATED)
this.value = value;
else
throw new BuildException("bad value type");
}
/**
* Sets the value of the receiver to be an array of items.
*
* @param value An array of strings to place in the option reference.
* @throws BuildException
*/
public void setValue(String [] value) throws BuildException {
if (getValueType() == IOption.STRING_LIST)
this.value = value;
if (getValueType() == IOption.STRING_LIST) {
// Just replace what the option reference is holding onto
this.value = new ArrayList(Arrays.asList(value));
}
else
throw new BuildException("bad value type");
}

View file

@ -1,11 +1,16 @@
/*
* Created on Apr 13, 2003
*
* To change the template for this generated file go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
package org.eclipse.cdt.internal.core.build.managed;
/**********************************************************************
* Copyright (c) 2002,2003 Rational Software Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v0.5
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v05.html
*
* Contributors:
* IBM Rational Software - Initial API and implementation
* **********************************************************************/
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -16,12 +21,6 @@ import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* @author dschaefe
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class ResourceBuildInfo {
private IResource owner;
@ -41,7 +40,6 @@ public class ResourceBuildInfo {
if (child.getNodeName().equals("target")) {
new Target(this, (Element)child);
}
child = child.getNextSibling();
}
}

View file

@ -51,11 +51,12 @@ public class Target extends BuildObject implements ITarget {
* @param parent
*/
public Target(IResource owner, ITarget parent) {
// Make the owner of the target the project resource
this(owner);
this.parent = parent;
// Copy the parent's identity
setId(parent.getId());
this.parent = parent;
setId(parent.getId() + ".1");
setName(parent.getName());
// Hook me up
@ -136,13 +137,18 @@ public class Target extends BuildObject implements ITarget {
if (child.getNodeName().equals("configuration")) {
new Configuration(this, (Element)child);
}
child = child.getNextSibling();
}
}
/**
* Persist receiver to project file.
*
* @param doc
* @param element
*/
public void serialize(Document doc, Element element) {
element.setAttribute("id", getId());
element.setAttribute("name", getName());
@ -155,7 +161,7 @@ public class Target extends BuildObject implements ITarget {
Configuration config = (Configuration)configurations.get(i);
Element configElement = doc.createElement("configuration");
element.appendChild(configElement);
config.serealize(doc, configElement);
config.serialize(doc, configElement);
}
}
@ -198,7 +204,14 @@ public class Target extends BuildObject implements ITarget {
}
public ITool getTool(String id) {
return (ITool)toolMap.get(id);
ITool result = null;
// See if receiver has it in list
result = (ITool)toolMap.get(id);
// If not, check if parent has it
if (result == null && parent != null) {
result = ((Target)parent).getTool(id);
}
return result;
}
public void addTool(ITool tool) {

View file

@ -36,10 +36,10 @@ public class ToolReference implements ITool {
private Map optionRefMap;
/**
* Created on the fly.
* Created a tool reference on the fly based on an existing tool.
*
* @param owner
* @param parent
* @param owner The <code>Configuration</code> the receiver will be added to.
* @param parent The <code>ITool</code>tool the reference will be based on.
*/
public ToolReference(Configuration owner, ITool parent) {
this.owner = owner;
@ -49,10 +49,10 @@ public class ToolReference implements ITool {
}
/**
* Created from extension.
* Created tool reference from an extension defined in a plugin manifest.
*
* @param owner
* @param element
* @param owner The <code>Configuration</code> the receiver will be added to.
* @param element The element containing build information for the reference.
*/
public ToolReference(Configuration owner, IConfigurationElement element) {
this.owner = owner;
@ -70,6 +70,13 @@ public class ToolReference implements ITool {
}
}
/**
* Create a new tool reference based on information contained in a project file.
*
* @param owner The <code>Configuration</code> the receiver will be added to.
* @param element The element defined in the project file containing build information
* for the receiver.
*/
public ToolReference(Configuration owner, Element element) {
this.owner = owner;
@ -87,7 +94,14 @@ public class ToolReference implements ITool {
}
}
public void serealize(Document doc, Element element) {
/**
* Persist receiver to project file.
*
* @param doc The persistent store for the reference information.
* @param element The root element in the store the receiver must use
* to persist settings.
*/
public void serialize(Document doc, Element element) {
element.setAttribute("id", parent.getId());
if (optionReferences != null)
@ -95,7 +109,7 @@ public class ToolReference implements ITool {
OptionReference optionRef = (OptionReference)optionReferences.get(i);
Element optionRefElement = doc.createElement("optionRef");
element.appendChild(optionRefElement);
optionRef.serealize(doc, optionRefElement);
optionRef.serialize(doc, optionRefElement);
}
}

View file

@ -114,6 +114,17 @@
</run>
</builder>
</extension>
<extension
id="genmakebuilder"
name="%GeneratedMakefileCBuilder.name"
point="org.eclipse.core.resources.builders">
<builder
hasNature="true">
<run
class="org.eclipse.cdt.internal.core.GeneratedMakefileBuilder">
</run>
</builder>
</extension>
<extension
id="problem"
name="%CProblemMarker.name"
@ -145,6 +156,22 @@
</run>
</runtime>
</extension>
<extension
id="managedBuildNature"
name="%ManagedBuildNature.name"
point="org.eclipse.core.resources.natures">
<requires-nature
id="org.eclipse.cdt.core.cnature">
</requires-nature>
<runtime>
<run
class="org.eclipse.cdt.core.ManagedCProjectNature">
</run>
</runtime>
<builder
id="org.eclipse.cdt.core.genmakebuilder">
</builder>
</extension>
<extension
point="org.eclipse.cdt.core.CBuildCommand">
<buildcommand
@ -252,29 +279,5 @@
pattern="*.exe">
</ignore>
</extension>
<extension
id="managedBuildNature"
name="%ManagedBuildNature.name"
point="org.eclipse.core.resources.natures">
<requires-nature
id="org.eclipse.cdt.core.cnature">
</requires-nature>
<runtime>
<run
class="org.eclipse.cdt.core.ManagedCProjectNature">
</run>
</runtime>
</extension>
<extension
id="generatedMakefileCBuilder"
name="%GeneratedMakefileCBuilder.name"
point="org.eclipse.core.resources.builders">
<builder
hasNature="true">
<run
class="org.eclipse.cdt.internal.core.GeneratedMakefileCBuilder">
</run>
</builder>
</extension>
</plugin>

View file

@ -0,0 +1,165 @@
package org.eclipse.cdt.core;
/**********************************************************************
* Copyright (c) 2002,2003 Rational Software Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v0.5
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v05.html
*
* Contributors:
* IBM Rational Software - Initial API and implementation
***********************************************************************/
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IProjectNature;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPluginDescriptor;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Plugin;
public class ManagedCProjectNature implements IProjectNature {
public static final String BUILDER_NAME= "genmakebuilder";
public static final String BUILDER_ID= CCorePlugin.PLUGIN_ID + "." + BUILDER_NAME;
private static final String MNG_NATURE_ID = CCorePlugin.PLUGIN_ID + ".managedBuildNature";
private IProject project;
/**
* Utility method for adding a managed nature to a project.
*
* @param proj the project to add the managed nature to.
* @param monitor a progress monitor to indicate the duration of the operation, or
* <code>null</code> if progress reporting is not required.
*/
public static void addManagedNature(IProject project, IProgressMonitor monitor) throws CoreException {
addNature(project, MNG_NATURE_ID, monitor);
}
public static void addManagedBuilder(IProject project, IProgressMonitor monitor) throws CoreException {
// Add the builder to the project
IProjectDescription description = project.getDescription();
ICommand[] commands = description.getBuildSpec();
boolean found = false;
// See if the builder is already there
for (int i = 0; i < commands.length; ++i) {
if (commands[i].getBuilderName().equals(getBuilderID())) {
found = true;
break;
}
}
if (!found) {
//add builder to project
ICommand command = description.newCommand();
command.setBuilderName(getBuilderID());
ICommand[] newCommands = new ICommand[commands.length + 1];
// Add it before other builders.
System.arraycopy(commands, 0, newCommands, 1, commands.length);
newCommands[0] = command;
description.setBuildSpec(newCommands);
project.setDescription(description, null);
}
}
/**
* Utility method for adding a nature to a project.
*
* @param proj the project to add the nature to.
* @param natureId the id of the nature to assign to the project
* @param monitor a progress monitor to indicate the duration of the operation, or
* <code>null</code> if progress reporting is not required.
*/
public static void addNature(IProject project, String natureId, IProgressMonitor monitor) throws CoreException {
IProjectDescription description = project.getDescription();
String[] prevNatures = description.getNatureIds();
for (int i = 0; i < prevNatures.length; i++) {
if (natureId.equals(prevNatures[i]))
return;
}
String[] newNatures = new String[prevNatures.length + 1];
System.arraycopy(prevNatures, 0, newNatures, 0, prevNatures.length);
newNatures[prevNatures.length] = natureId;
description.setNatureIds(newNatures);
project.setDescription(description, monitor);
}
/**
* Get the correct builderID
*/
public static String getBuilderID() {
Plugin plugin = (Plugin)CCorePlugin.getDefault();
IPluginDescriptor descriptor = plugin.getDescriptor();
if (descriptor.getExtension(BUILDER_NAME) != null) {
return descriptor.getUniqueIdentifier() + "." + BUILDER_NAME;
}
return BUILDER_ID;
}
/* (non-Javadoc)
* @see org.eclipse.core.resources.IProjectNature#configure()
*/
public void configure() throws CoreException {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see org.eclipse.core.resources.IProjectNature#deconfigure()
*/
public void deconfigure() throws CoreException {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see org.eclipse.core.resources.IProjectNature#getProject()
*/
public IProject getProject() {
// Just return the project associated with the nature
return project;
}
/**
* Utility method to remove the managed nature from a project.
*
* @param project to remove the managed nature from
* @param mon progress monitor to indicate the duration of the operation, or
* <code>null</code> if progress reporting is not required.
* @throws CoreException
*/
public static void removeManagedNature(IProject project, IProgressMonitor mon) throws CoreException {
removeNature(project, MNG_NATURE_ID, mon);
}
/**
* Utility method for removing a project nature from a project.
*
* @param proj the project to remove the nature from
* @param natureId the nature id to remove
* @param monitor a progress monitor to indicate the duration of the operation, or
* <code>null</code> if progress reporting is not required.
*/
public static void removeNature(IProject project, String natureId, IProgressMonitor monitor) throws CoreException {
IProjectDescription description = project.getDescription();
String[] prevNatures = description.getNatureIds();
List newNatures = new ArrayList(Arrays.asList(prevNatures));
newNatures.remove(natureId);
description.setNatureIds((String[])newNatures.toArray(new String[newNatures.size()]));
project.setDescription(description, monitor);
}
/* (non-Javadoc)
* @see org.eclipse.core.resources.IProjectNature#setProject(org.eclipse.core.resources.IProject)
*/
public void setProject(IProject project) {
// Set the project for the nature
this.project = project;
}
}

View file

@ -5,3 +5,7 @@
#
################################################
CBuilder.build_error= Build Error
# Generated makefile builder messages
MakeBuilder.message.rebuild = Regenerating makefile for project {0}
MakeBuilder.message.incremental = Updating makefile for project {0}

View file

@ -0,0 +1,250 @@
package org.eclipse.cdt.internal.core;
/**********************************************************************
* Copyright (c) 2002,2003 Rational Software Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v0.5
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v05.html
*
* Contributors:
* IBM Rational Software - Initial API and implementation
* **********************************************************************/
import java.io.ByteArrayInputStream;
import java.util.Map;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.build.managed.ManagedBuildManager;
import org.eclipse.cdt.core.resources.ACBuilder;
import org.eclipse.cdt.core.resources.MakeUtil;
import org.eclipse.cdt.internal.core.build.managed.ResourceBuildInfo;
import org.eclipse.cdt.internal.core.model.Util;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IResourceStatus;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
public class GeneratedMakefileBuilder extends ACBuilder {
// String constants
private static final String MESSAGE = "MakeBuilder.message"; //$NON-NLS-1$
private static final String REBUILD = MESSAGE + ".rebuild"; //$NON-NLS-1$
private static final String INCREMENTAL = MESSAGE + ".incremental"; //$NON-NLS-1$
private static final String FILENAME = "makefile"; //$NON-NLS-1$
private static final String NEWLINE = System.getProperty("line.separator", "\n"); //$NON-NLS-1$
private static final String TAB = "\t"; //$NON-NLS-1$
public class MyResourceDeltaVisitor implements IResourceDeltaVisitor {
boolean bContinue;
public boolean visit(IResourceDelta delta) throws CoreException {
IResource resource = delta.getResource();
if (resource != null && resource.getProject() == getProject()) {
bContinue = true;
return false;
}
return true;
}
public boolean shouldBuild() {
return bContinue;
}
}
/**
*
*/
public GeneratedMakefileBuilder() {
super();
}
/**
* @param buffer
*/
private void addMacros(StringBuffer buffer, ResourceBuildInfo info) {
// TODO this should come from the build model
buffer.append("CC = " + NEWLINE);
buffer.append("CFLAGS = " + NEWLINE);
buffer.append("LD = " + NEWLINE);
buffer.append("LDFLAGS = " + NEWLINE);
buffer.append("RM = rm -f" + NEWLINE);
buffer.append("MAKE = make" + NEWLINE);
buffer.append(NEWLINE);
}
/**
* @param buffer
*/
private void addTargets(StringBuffer buffer) {
// TODO Targets should come from build model
// TODO Generate 'all' for now
buffer.append("all:" + NEWLINE);
buffer.append(NEWLINE);
// Always add a clean target
buffer.append("clean:" + NEWLINE);
buffer.append(TAB + "$(RM) *.o" + NEWLINE);
buffer.append(NEWLINE);
}
/* (non-Javadoc)
* @see org.eclipse.core.internal.events.InternalBuilder#build(int, java.util.Map, org.eclipse.core.runtime.IProgressMonitor)
*/
protected IProject[] build(int kind, Map args, IProgressMonitor monitor) throws CoreException {
if (kind == IncrementalProjectBuilder.FULL_BUILD) {
fullBuild(monitor);
}
else {
// Create a delta visitor to make sure we should be rebuilding
MyResourceDeltaVisitor visitor = new MyResourceDeltaVisitor();
IResourceDelta delta = getDelta(getProject());
if (delta == null) {
fullBuild(monitor);
}
else {
delta.accept(visitor);
if (visitor.shouldBuild()) {
incrementalBuild(delta, monitor);
}
}
}
// Checking to see if the user cancelled the build
checkCancel(monitor);
// Build referenced projects
return getProject().getReferencedProjects();
}
/**
* Check whether the build has been canceled.
*/
public void checkCancel(IProgressMonitor monitor) {
if (monitor != null && monitor.isCanceled())
throw new OperationCanceledException();
}
/**
* @param monitor
*/
private void fullBuild(IProgressMonitor monitor) throws CoreException {
// Rebuild the entire project
IProject currentProject = getProject();
String statusMsg = null;
// Need to report status to the user
if (monitor == null) {
monitor = new NullProgressMonitor();
}
statusMsg = CCorePlugin.getFormattedString(REBUILD, currentProject.getName());
monitor.subTask(statusMsg);
// Get a filehandle for the makefile
IPath filePath = getWorkingDirectory().append(IPath.SEPARATOR + FILENAME);
String temp = filePath.toString();
IFile fileHandle = getMakefile(filePath, monitor);
// Add the items to the makefile
populateMakefile(fileHandle, monitor);
monitor.worked(1);
}
/**
* Gets the makefile for the project. It may be empty.
*
* @return The <code>IFile</code> to generate the makefile into.
*/
public IFile getMakefile(IPath filePath, IProgressMonitor monitor) throws CoreException {
// Create or get the handle for the makefile
IWorkspaceRoot root= CCorePlugin.getWorkspace().getRoot();
IFile newFile = root.getFileForLocation(filePath);
if (newFile == null) {
newFile = root.getFile(filePath);
}
// Create the file if it does not exist
ByteArrayInputStream contents = new ByteArrayInputStream(new byte[0]);
try {
newFile.create(contents, false, monitor);
}
catch (CoreException e) {
// If the file already existed locally, just refresh to get contents
if (e.getStatus().getCode() == IResourceStatus.PATH_OCCUPIED)
newFile.refreshLocal(IResource.DEPTH_ZERO, null);
else
throw e;
}
// TODO handle long running file operation
return newFile;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.resources.ACBuilder#getWorkingDirectory()
*/
public IPath getWorkingDirectory() {
IProject currProject = getProject();
IPath workingDirectory = new Path(MakeUtil.getSessionBuildDir((IResource) currProject));
if (workingDirectory.isEmpty())
workingDirectory = currProject.getLocation();
return workingDirectory;
}
/**
* @param delta
* @param monitor
*/
private void incrementalBuild(IResourceDelta delta, IProgressMonitor monitor) throws CoreException {
// Rebuild the resource tree in the delta
IProject currentProject = getProject();
String statusMsg = null;
// Need to report status to the user
if (monitor == null) {
monitor = new NullProgressMonitor();
}
statusMsg = CCorePlugin.getFormattedString(INCREMENTAL, currentProject.getName());
monitor.subTask(statusMsg);
// Get a filehandle for the makefile
IPath filePath = getWorkingDirectory();
filePath.addTrailingSeparator();
filePath.append(FILENAME);
IFile fileHandle = getMakefile(filePath, monitor);
// Now populate it
populateMakefile(fileHandle, monitor);
monitor.worked(1);
}
/**
* Recreate the entire contents of the makefile.
*
* @param fileHandle The file to place the contents in.
*/
private void populateMakefile(IFile fileHandle, IProgressMonitor monitor) throws CoreException {
// Write out the contents of the build model
StringBuffer buffer = new StringBuffer();
ResourceBuildInfo info = ManagedBuildManager.getBuildInfo(getProject());
// Add the macro definitions
addMacros(buffer, info);
// Add targets
addTargets(buffer);
// Save the file
Util.save(buffer, fileHandle);
}
}

View file

@ -10,6 +10,8 @@
**********************************************************************/
package org.eclipse.cdt.core.build.managed.tests;
import java.util.Arrays;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
@ -32,6 +34,12 @@ import org.eclipse.core.runtime.CoreException;
*
*/
public class AllBuildTests extends TestCase {
private static final boolean boolVal = true;
private static final String newConfigName = "test.config.override";
private static final String enumVal = "Another Enum";
private static final String[] listVal = {"_DEBUG", "/usr/include", "libglade.a"};
private static final String projectName = "BuildTest";
private static final String stringVal = "-c -wall";
public AllBuildTests(String name) {
super(name);
@ -42,6 +50,7 @@ public class AllBuildTests extends TestCase {
suite.addTest(new AllBuildTests("testExtensions"));
suite.addTest(new AllBuildTests("testProject"));
suite.addTest(new AllBuildTests("testConfigurations"));
return suite;
}
@ -97,9 +106,55 @@ public class AllBuildTests extends TestCase {
assertNotNull(testSub);
}
public void testConfigurations() throws CoreException, BuildException {
// Open the test project
IProject project = createProject(projectName);
// Make sure there is one and only one target with 2 configs
ITarget[] definedTargets = ManagedBuildManager.getTargets(project);
assertEquals(1, definedTargets.length);
ITarget rootTarget = definedTargets[0];
IConfiguration[] definedConfigs = rootTarget.getConfigurations();
assertEquals(2, definedConfigs.length);
IConfiguration baseConfig = definedConfigs[0];
// Create a new configuration
IConfiguration newConfig = rootTarget.createConfiguration(baseConfig, newConfigName);
assertEquals(3, rootTarget.getConfigurations().length);
// There is only one tool
ITool[] definedTools = newConfig.getTools();
assertEquals(1, definedTools.length);
ITool rootTool = definedTools[0];
// Override options in the new configuration
IOptionCategory topCategory = rootTool.getTopOptionCategory();
assertEquals("Root Tool", topCategory.getName());
IOption[] options = topCategory.getOptions(null);
assertEquals(2, options.length);
ManagedBuildManager.setOption(newConfig, options[0], listVal);
ManagedBuildManager.setOption(newConfig, options[1], boolVal);
IOptionCategory[] categories = topCategory.getChildCategories();
assertEquals(1, categories.length);
options = categories[0].getOptions(null);
assertEquals(2, options.length);
ManagedBuildManager.setOption(newConfig, options[0], stringVal);
ManagedBuildManager.setOption(newConfig, options[1], enumVal);
// Save, close, reopen and test again
ManagedBuildManager.saveBuildInfo(project);
project.close(null);
ManagedBuildManager.removeBuildInfo(project);
project.open(null);
// Test the values in the new configuration
checkOptionReferences(project);
}
public void testProject() throws CoreException, BuildException {
// Create new project
IProject project = createProject("BuildTest");
IProject project = createProject(projectName);
assertEquals(0, ManagedBuildManager.getTargets(project).length);
@ -125,7 +180,7 @@ public class AllBuildTests extends TestCase {
checkRootTarget(target, "x");
// Override the "Option in Category" option value
// Override the "String Option in Category" option value
configs = target.getConfigurations();
ITool[] tools = configs[0].getTools();
IOptionCategory topCategory = tools[0].getTopOptionCategory();
@ -166,6 +221,57 @@ public class AllBuildTests extends TestCase {
return project;
}
private void checkOptionReferences(IProject project) throws BuildException {
// Get the targets out of the project
ITarget[] definedTargets = ManagedBuildManager.getTargets(project);
assertEquals(1, definedTargets.length);
ITarget rootTarget = definedTargets[0];
// Now get the configs
IConfiguration[] definedConfigs = rootTarget.getConfigurations();
assertEquals(3, definedConfigs.length);
IConfiguration newConfig = rootTarget.getConfiguration(newConfigName);
assertNotNull(newConfig);
// Now get the tool options and make sure the values are correct
ITool[] definedTools = newConfig.getTools();
assertEquals(1, definedTools.length);
ITool rootTool = definedTools[0];
// Check that the options in the new config contain overridden values
IOption[] rootOptions = rootTool.getOptions();
assertEquals(4, rootOptions.length);
// First is the new list
assertEquals("List Option in Top", rootOptions[0].getName());
assertEquals(IOption.STRING_LIST, rootOptions[0].getValueType());
String[] list = rootOptions[0].getStringListValue();
assertEquals(3, list.length);
assertTrue(Arrays.equals(listVal, list));
assertEquals(rootOptions[0].getCommand(), "-L");
// Next option is a boolean in top
assertEquals("Boolean Option in Top", rootOptions[1].getName());
assertEquals(IOption.BOOLEAN, rootOptions[1].getValueType());
assertEquals(boolVal, rootOptions[1].getBooleanValue());
assertEquals("-b", rootOptions[1].getCommand());
// Next option is a string category
assertEquals("String Option in Category", rootOptions[2].getName());
assertEquals(IOption.STRING, rootOptions[2].getValueType());
assertEquals(stringVal, rootOptions[2].getStringValue());
// Final option is an enumerated
assertEquals("Enumerated Option in Category", rootOptions[3].getName());
assertEquals(IOption.ENUMERATED, rootOptions[3].getValueType());
String selEnum = rootOptions[3].getSelectedEnum();
assertEquals(enumVal, selEnum);
String[] enums = rootOptions[3].getApplicableValues();
assertEquals(2, enums.length);
assertEquals("Default Enum", enums[0]);
assertEquals("Another Enum", enums[1]);
assertEquals("-e1", rootOptions[3].getEnumCommand(enums[0]));
assertEquals("-e2", rootOptions[3].getEnumCommand(enums[1]));
assertEquals("-e2", rootOptions[3].getEnumCommand(selEnum));
}
private void checkRootTarget(ITarget target, String oicValue) throws BuildException {
// Tools
ITool[] tools = target.getTools();
@ -195,7 +301,7 @@ public class AllBuildTests extends TestCase {
// Final option is an enumerated
assertEquals("Enumerated Option in Category", options[3].getName());
assertEquals(IOption.ENUMERATED, options[3].getValueType());
assertEquals("Default Enum", options[3].getDefaultEnumName());
assertEquals("Default Enum", options[3].getSelectedEnum());
valueList = options[3].getApplicableValues();
assertEquals(2, valueList.length);
assertEquals("Default Enum", valueList[0]);
@ -241,6 +347,7 @@ public class AllBuildTests extends TestCase {
assertEquals("String Option in Category", options[0].getName());
assertEquals(oicValue, options[0].getStringValue());
assertEquals("Enumerated Option in Category", options[1].getName());
// Root Override Config
assertEquals("Root Override Config", configs[1].getName());
tools = configs[1].getTools();

View file

@ -108,7 +108,7 @@
name="List Option in Top"
command="-L"
valueType="stringList"
id="topOption">
id="list.option">
<optionValue
value="a">
</optionValue>
@ -121,20 +121,20 @@
name="Boolean Option in Top"
command="-b"
valueType="boolean"
id="topBoolOption">
id="boolean.option">
</option>
<option
defaultValue="x"
name="String Option in Category"
category="category"
valueType="string"
id="childOption">
id="string.option">
</option>
<option
name="Enumerated Option in Category"
category="category"
valueType="enumerated"
id="child.enumerated.option">
id="enumerated.option">
<optionEnum
name="Default Enum"
value="s"
@ -162,7 +162,11 @@
<optionRef
defaultValue="y"
value="y"
id="childOption">
id="string.option">
</optionRef>
<optionRef
defaultValue="true"
id="boolean.option">
</optionRef>
</toolRef>
</configuration>