mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-09 10:46:02 +02:00
Fix for bug 66739 - Created a shared lib project does not set shared flag in configs. There was a gap in the ever-increasingly complex inheritance behaviour of the ToolReferences. The commands supplied by the ToolReferences were being ignored if the configuration supplied its own ToolReferences. Searching is more comprehensive now, the tool reference is creating a copy of itself more thoroughly, and the JUnit tests have been updated to reflect this.
This commit is contained in:
parent
3783f1b7be
commit
687d762517
7 changed files with 223 additions and 38 deletions
|
@ -38,7 +38,7 @@
|
|||
name="String in Free"
|
||||
category="indy.cat.free"
|
||||
valueType="string"
|
||||
id="org.eclipse.cdt.core.tests.option1">
|
||||
id="indy.cat.free.string">
|
||||
</option>
|
||||
<optionCategory
|
||||
owner="indy.cat.free"
|
||||
|
@ -50,7 +50,7 @@
|
|||
name="Boolean in Chained"
|
||||
category="indy.cat.chained"
|
||||
valueType="boolean"
|
||||
id="org.eclipse.cdt.core.tests.option2">
|
||||
id="indy.cat.chained.boolean">
|
||||
</option>
|
||||
</tool>
|
||||
<target
|
||||
|
@ -293,7 +293,13 @@
|
|||
id="test.sub.sub">
|
||||
<toolReference
|
||||
id="target.independent.tool">
|
||||
<optionReference
|
||||
defaultValue="true"
|
||||
id="indy.cat.chained.boolean"/>
|
||||
</toolReference>
|
||||
<configuration
|
||||
name="Sub Sub Config"
|
||||
id="sub.sub.config"/>
|
||||
</target>
|
||||
<dynamicElementProvider
|
||||
name="Test Target Provider"
|
||||
|
|
|
@ -45,7 +45,9 @@ import org.eclipse.cdt.managedbuilder.core.ITool;
|
|||
import org.eclipse.cdt.managedbuilder.core.IToolReference;
|
||||
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
|
||||
import org.eclipse.cdt.managedbuilder.core.ManagedCProjectNature;
|
||||
import org.eclipse.cdt.managedbuilder.internal.core.Option;
|
||||
import org.eclipse.cdt.managedbuilder.internal.core.OptionReference;
|
||||
import org.eclipse.cdt.managedbuilder.internal.core.ToolReference;
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.resources.IFolder;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
|
@ -1052,6 +1054,24 @@ public class ManagedBuildCoreTests extends TestCase {
|
|||
}
|
||||
|
||||
/*
|
||||
* The Sub Sub target has a reference to a tool that is defined
|
||||
* independently from the target itself. This is a common pattern
|
||||
* for tools that are shared between many targets.
|
||||
*
|
||||
* The tool itself is defined as having two option categories, with
|
||||
* one option in each category. To test that the reference is properly
|
||||
* inheritted, the target overrides the default value of the boolean
|
||||
* option.
|
||||
*
|
||||
* The test confirms that the basic settings are inheritted through the
|
||||
* reference, and that the overridden value is used instead of the
|
||||
* default. It also tests that the command can be overidden through a
|
||||
* tool reference.
|
||||
*
|
||||
* Finally, the string option in the configuration is overridden and the
|
||||
* test confirms that it contains both the overridden boolean that the
|
||||
* target provides, and the overridden string that it provides.
|
||||
*
|
||||
* @param testSubSub
|
||||
*/
|
||||
private void checkSubSubTarget(ITarget target) {
|
||||
|
@ -1068,6 +1088,7 @@ public class ManagedBuildCoreTests extends TestCase {
|
|||
final String chainedOptName = "Boolean in Chained";
|
||||
final String freeOptValue = "Live free or die";
|
||||
final String newCmd = "Let the Wookie win";
|
||||
final String stringOverride = "The future language of slaves";
|
||||
|
||||
// Check the inherited clean command
|
||||
assertEquals("rm -yourworld", target.getCleanCommand());
|
||||
|
@ -1079,9 +1100,9 @@ public class ManagedBuildCoreTests extends TestCase {
|
|||
String[] expectedOSList = {"win32","linux","solaris"};
|
||||
assertTrue(Arrays.equals(expectedOSList, target.getTargetOSList()));
|
||||
|
||||
// Get the 4 configurations
|
||||
// Get the 5 configurations (3 from test, 1 from test sub and 1 from this)
|
||||
IConfiguration[] configs = target.getConfigurations();
|
||||
assertEquals(4, configs.length);
|
||||
assertEquals(5, configs.length);
|
||||
|
||||
// Check the tools. We should have 3 (1 from each parent and the one referenced).
|
||||
ITool[] tools = target.getTools();
|
||||
|
@ -1115,7 +1136,13 @@ public class ManagedBuildCoreTests extends TestCase {
|
|||
assertEquals(freeOptName, optsInCat[0].getName());
|
||||
assertEquals(IOption.STRING, optsInCat[0].getValueType());
|
||||
try {
|
||||
assertEquals(freeOptValue, optsInCat[0].getStringValue());
|
||||
// We get the option categories and options from the tool itself, but the
|
||||
// tool reference will have a set of 0 to n option references that contain
|
||||
// overridden settings. In this case, the string is inheritted and should
|
||||
// not be reference
|
||||
IOption stringOpt = toolRef.getOptionById(optsInCat[0].getId());
|
||||
assertTrue(stringOpt instanceof Option);
|
||||
assertEquals(freeOptValue, stringOpt.getStringValue());
|
||||
} catch (BuildException e1) {
|
||||
fail("Failed getting string value in subsubtarget :" + e1.getLocalizedMessage());
|
||||
}
|
||||
|
@ -1123,10 +1150,12 @@ public class ManagedBuildCoreTests extends TestCase {
|
|||
// Do the same for the options in the child cat
|
||||
IOption[] optsInSubCat = subCategories[0].getOptions(null);
|
||||
assertEquals(1, optsInSubCat.length);
|
||||
assertEquals(chainedOptName, optsInSubCat[0].getName());
|
||||
assertEquals(IOption.BOOLEAN, optsInSubCat[0].getValueType());
|
||||
IOption booleanRef = toolRef.getOptionById(optsInSubCat[0].getId());
|
||||
assertTrue(booleanRef instanceof OptionReference);
|
||||
assertEquals(chainedOptName, booleanRef.getName());
|
||||
assertEquals(IOption.BOOLEAN, booleanRef.getValueType());
|
||||
try {
|
||||
assertFalse(optsInSubCat[0].getBooleanValue());
|
||||
assertTrue(booleanRef.getBooleanValue());
|
||||
} catch (BuildException e) {
|
||||
fail("Failure getting boolean value in subsubtarget: " + e.getLocalizedMessage());
|
||||
}
|
||||
|
@ -1134,6 +1163,57 @@ public class ManagedBuildCoreTests extends TestCase {
|
|||
// Test that the tool command can be changed through the reference
|
||||
((IToolReference)toolRef).setToolCommand(newCmd);
|
||||
assertEquals(toolRef.getToolCommand(), newCmd);
|
||||
|
||||
// Muck about with the options in the local config
|
||||
IConfiguration subSubConfig = target.getConfiguration("sub.sub.config");
|
||||
assertNotNull(subSubConfig);
|
||||
ITool[] configTools = subSubConfig.getTools();
|
||||
// This tool ref is inherited from parent, so it does not belong to the config
|
||||
ITool configToolRef = configTools[2];
|
||||
assertNotNull(configToolRef);
|
||||
assertFalse(((ToolReference)configToolRef).ownedByConfiguration(subSubConfig));
|
||||
IOption configStringOpt = configToolRef.getOptionById(optsInCat[0].getId());
|
||||
assertNotNull(configStringOpt);
|
||||
// Override the string option
|
||||
try {
|
||||
subSubConfig.setOption(configStringOpt, stringOverride);
|
||||
} catch (BuildException e) {
|
||||
fail("Failure setting string value in subsubconfiguration: " + e.getLocalizedMessage());
|
||||
}
|
||||
// Now the config should have a tool ref to the independent tool
|
||||
configTools = subSubConfig.getTools();
|
||||
configToolRef = configTools[2];
|
||||
assertNotNull(configToolRef);
|
||||
assertTrue(((ToolReference)configToolRef).ownedByConfiguration(subSubConfig));
|
||||
|
||||
// Test that the string option is overridden in the configuration
|
||||
configStringOpt = configToolRef.getOptionById(optsInCat[0].getId());
|
||||
try {
|
||||
assertEquals(stringOverride, configStringOpt.getStringValue());
|
||||
} catch (BuildException e) {
|
||||
fail("Failure getting string value in subsubconfiguration: " + e.getLocalizedMessage());
|
||||
}
|
||||
// The tool should also contain the boolean option set to true
|
||||
IOption configBoolOpt = configToolRef.getOptionById(optsInSubCat[0].getId());
|
||||
assertNotNull(configBoolOpt);
|
||||
try {
|
||||
assertTrue(configBoolOpt.getBooleanValue());
|
||||
} catch (BuildException e) {
|
||||
fail("Failure getting boolean value in subsubconfiguration: " + e.getLocalizedMessage());
|
||||
}
|
||||
|
||||
// Override it in config and retest
|
||||
try {
|
||||
subSubConfig.setOption(configBoolOpt, false);
|
||||
} catch (BuildException e) {
|
||||
fail("Failure setting boolean value in subsubconfiguration: " + e.getLocalizedMessage());
|
||||
}
|
||||
configBoolOpt = configToolRef.getOptionById(optsInSubCat[0].getId());
|
||||
try {
|
||||
assertFalse(configBoolOpt.getBooleanValue());
|
||||
} catch (BuildException e) {
|
||||
fail("Failure getting boolean value in subsubconfiguration: " + e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -72,8 +72,9 @@ public interface ITool extends IBuildObject {
|
|||
|
||||
/**
|
||||
* This is a deprecated method for retrieving an <code>IOption</code> from
|
||||
* the receiver based on an ID. It is preferred that you use the newer method
|
||||
* @see org.eclipse.cdt.core.build.managed.ITool#getOption(java.lang.String)
|
||||
* the receiver based on an ID. It is preferred that you use the newer method
|
||||
* <code>getOptionById</code>
|
||||
* @see org.eclipse.cdt.core.build.managed.ITool#getOptionById(java.lang.String)
|
||||
*
|
||||
* @param id unique identifier of the option to search for
|
||||
* @return <code>IOption</code>
|
||||
|
|
|
@ -104,9 +104,10 @@ public class Configuration extends BuildObject implements IConfiguration {
|
|||
// Check that the tool and the project match
|
||||
IProject project = (IProject) target.getOwner();
|
||||
|
||||
// Get the tool references from the parent
|
||||
List parentToolRefs = ((Configuration)parentConfig).getLocalToolReferences();
|
||||
Iterator iter = parentToolRefs.listIterator();
|
||||
// Get the tool references from the target and parent
|
||||
List allToolRefs = new Vector(target.getLocalToolReferences());
|
||||
allToolRefs.addAll(((Configuration)parentConfig).getLocalToolReferences());
|
||||
Iterator iter = allToolRefs.listIterator();
|
||||
while (iter.hasNext()) {
|
||||
ToolReference toolRef = (ToolReference)iter.next();
|
||||
|
||||
|
@ -231,35 +232,60 @@ public class Configuration extends BuildObject implements IConfiguration {
|
|||
* @return
|
||||
*/
|
||||
private OptionReference createOptionReference(IOption option) {
|
||||
ToolReference searchRef = null;
|
||||
ToolReference answer = null;
|
||||
// The option may already be a reference created to hold user settings
|
||||
if (option instanceof OptionReference) {
|
||||
// The option reference belongs to an existing tool reference
|
||||
OptionReference optionRef = (OptionReference)option;
|
||||
ToolReference toolRef = optionRef.getToolReference();
|
||||
searchRef = optionRef.getToolReference();
|
||||
|
||||
// That tool reference may belong to a target or to the configuration
|
||||
if (toolRef.ownedByConfiguration(this))
|
||||
if (searchRef.ownedByConfiguration(this))
|
||||
return optionRef;
|
||||
else {
|
||||
// Make a copy so the settings can be saved
|
||||
toolRef = new ToolReference(this, toolRef);
|
||||
return toolRef.createOptionReference(option);
|
||||
// All this means is that the tool ref does not belong to the receiver.
|
||||
// The receiver may also have a reference to the tool
|
||||
if ((answer = findLocalReference(searchRef)) == null) {
|
||||
// Otherwise, create one and save the option setting in it
|
||||
answer = new ToolReference(this, searchRef);
|
||||
}
|
||||
return answer.createOptionReference(option);
|
||||
}
|
||||
} else {
|
||||
// Find out if a tool reference already exists
|
||||
ToolReference toolRef = (ToolReference) getToolReference(option.getTool());
|
||||
if (toolRef == null) {
|
||||
toolRef = new ToolReference(this, option.getTool());
|
||||
searchRef = (ToolReference) getToolReference(option.getTool());
|
||||
if (searchRef == null) {
|
||||
answer = new ToolReference(this, option.getTool());
|
||||
} else {
|
||||
// The reference may belong to the target
|
||||
if (!toolRef.ownedByConfiguration(this)) {
|
||||
toolRef = new ToolReference(this, toolRef);
|
||||
if (!searchRef.ownedByConfiguration(this)) {
|
||||
answer = new ToolReference(this, searchRef);
|
||||
} else {
|
||||
answer = searchRef;
|
||||
}
|
||||
}
|
||||
|
||||
return toolRef.createOptionReference(option);
|
||||
return answer.createOptionReference(option);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @param toolRef
|
||||
* @return
|
||||
*/
|
||||
private ToolReference findLocalReference(ToolReference toolRef) {
|
||||
Iterator iter = getLocalToolReferences().iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
ToolReference ref = (ToolReference)iter.next();
|
||||
if (toolRef.getTool().equals(ref.getTool())) {
|
||||
return ref;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.managedbuilder.core.IConfiguration#getFilteredTools(org.eclipse.core.resources.IProject)
|
||||
*/
|
||||
|
|
|
@ -502,7 +502,7 @@ public class Target extends BuildObject implements ITarget {
|
|||
*
|
||||
* @return List
|
||||
*/
|
||||
private List getLocalToolReferences() {
|
||||
protected List getLocalToolReferences() {
|
||||
if (toolReferences == null) {
|
||||
toolReferences = new ArrayList();
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.eclipse.cdt.managedbuilder.core.IOptionCategory;
|
|||
import org.eclipse.cdt.managedbuilder.core.ITool;
|
||||
import org.eclipse.cdt.managedbuilder.core.IToolReference;
|
||||
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
|
||||
import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
@ -149,15 +150,19 @@ public class ToolReference implements IToolReference {
|
|||
* Created a tool reference on the fly based on an existing tool or tool reference.
|
||||
*
|
||||
* @param owner The <code>BuildObject</code> the receiver will be added to.
|
||||
* @param parent The <code>ITool</code>tool the reference will be based on.
|
||||
* @param tool The <code>ITool</code>tool the reference will be based on.
|
||||
*/
|
||||
public ToolReference(BuildObject owner, ITool parent) {
|
||||
this.parent = parent;
|
||||
public ToolReference(BuildObject owner, ITool tool) {
|
||||
this.owner = owner;
|
||||
command = parent.getToolCommand();
|
||||
outputFlag = parent.getOutputFlag();
|
||||
outputPrefix = parent.getOutputPrefix();
|
||||
String[] extensions = parent.getOutputExtensions();
|
||||
if (tool instanceof ToolReference) {
|
||||
parent = ((ToolReference)tool).getTool();
|
||||
} else {
|
||||
parent = tool;
|
||||
}
|
||||
command = tool.getToolCommand();
|
||||
outputFlag = tool.getOutputFlag();
|
||||
outputPrefix = tool.getOutputPrefix();
|
||||
String[] extensions = tool.getOutputExtensions();
|
||||
outputExtensions = new String();
|
||||
if (extensions != null) {
|
||||
for (int index = 0; index < extensions.length; ++index) {
|
||||
|
@ -169,6 +174,34 @@ public class ToolReference implements IToolReference {
|
|||
}
|
||||
}
|
||||
|
||||
// Create a copy of the option references of the parent in the receiver
|
||||
if (tool instanceof ToolReference) {
|
||||
List parentRefs = ((ToolReference)tool).getOptionReferenceList();
|
||||
Iterator iter = parentRefs.iterator();
|
||||
while (iter.hasNext()) {
|
||||
IOption parent = (IOption)iter.next();
|
||||
OptionReference clone = createOptionReference(parent);
|
||||
try {
|
||||
switch (parent.getValueType()) {
|
||||
case IOption.BOOLEAN:
|
||||
clone.setValue(parent.getBooleanValue());
|
||||
break;
|
||||
case IOption.STRING:
|
||||
clone.setValue(parent.getStringValue());
|
||||
case IOption.ENUMERATED:
|
||||
clone.setValue(parent.getSelectedEnum());
|
||||
break;
|
||||
default:
|
||||
clone.setValue(parent.getStringListValue());
|
||||
break;
|
||||
}
|
||||
} catch (BuildException e) {
|
||||
ManagedBuilderCorePlugin.log(e);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (owner instanceof Configuration) {
|
||||
((Configuration)owner).addToolReference(this);
|
||||
} else if (owner instanceof Target) {
|
||||
|
@ -250,7 +283,14 @@ public class ToolReference implements IToolReference {
|
|||
public OptionReference createOptionReference(IOption option) {
|
||||
// Check if the option reference already exists
|
||||
OptionReference ref = getOptionReference(option);
|
||||
if (ref == null) {
|
||||
// It is possible that the search will return an option reference
|
||||
// that is supplied by another element of the build model, not the caller.
|
||||
// For example, if the search is starated by a configuration and the target
|
||||
// the caller belongs to has an option reference for the option, it
|
||||
// will be returned. While this is correct behaviour for a search, the
|
||||
// caller will need to create a clone for itself, so make sure the tool
|
||||
// reference of the search result is owned by the caller
|
||||
if (ref == null || !ref.getToolReference().owner.equals(this.owner)) {
|
||||
ref = new OptionReference(this, option);
|
||||
}
|
||||
return ref;
|
||||
|
@ -504,7 +544,6 @@ public class ToolReference implements IToolReference {
|
|||
public List getOptionReferenceList() {
|
||||
if (optionReferences == null) {
|
||||
optionReferences = new ArrayList();
|
||||
optionReferences.clear();
|
||||
}
|
||||
return optionReferences;
|
||||
}
|
||||
|
|
|
@ -222,7 +222,7 @@
|
|||
<option
|
||||
name="%Option.Posix.Linker.Defname"
|
||||
category="gnu.c.link.category.shared"
|
||||
command="-Wl,--output-def,"
|
||||
command="-Wl,--output-def="
|
||||
id="gnu.c.link.option.defname"
|
||||
valueType="string">
|
||||
</option>
|
||||
|
@ -307,7 +307,7 @@
|
|||
<option
|
||||
name="%Option.Posix.Linker.XLinker"
|
||||
category="gnu.cpp.link.category.other"
|
||||
command="-Xlinker,"
|
||||
command="-Xlinker "
|
||||
valueType="stringList"
|
||||
id="gnu.cpp.link.option.other">
|
||||
</option>
|
||||
|
@ -348,7 +348,7 @@
|
|||
<option
|
||||
name="%Option.Posix.Linker.Defname"
|
||||
category="gnu.cpp.link.category.shared"
|
||||
command="-Wl,--output-def,"
|
||||
command="-Wl,--output-def="
|
||||
valueType="string"
|
||||
id="gnu.cpp.link.option.defname">
|
||||
</option>
|
||||
|
@ -438,6 +438,27 @@
|
|||
name="%Option.Posix.UndefSym"
|
||||
id="gnu.windres.option.preprocessor.undefined.symbols"/>
|
||||
</tool-->
|
||||
<!--tool
|
||||
command="as"
|
||||
sources="s,S"
|
||||
outputs="o"
|
||||
name="%ToolName.assembler.gnu"
|
||||
outputFlag="-o"
|
||||
id="cdt.managedbuild.tool.gnu.assembler"
|
||||
natureFilter="both">
|
||||
<optionCategory
|
||||
owner="cdt.managedbuild.tool.gnu.assembler"
|
||||
name="%OptionCategory.General"
|
||||
id="gnu.asm.category.general">
|
||||
</optionCategory>
|
||||
<option
|
||||
name="%Option.Posix.Assembler.Flags"
|
||||
category="gnu.asm.category.general"
|
||||
valueType="string"
|
||||
id="gnu.both.asm.option.flags">
|
||||
</option>
|
||||
|
||||
<tool/-->
|
||||
<target
|
||||
name="%TargetName.gnu"
|
||||
id="cdt.managedbuild.target.gnu"
|
||||
|
@ -1047,11 +1068,17 @@
|
|||
outputs="so"
|
||||
outputPrefix="lib"
|
||||
id="cdt.managedbuild.tool.gnu.c.linker">
|
||||
<optionReference
|
||||
defaultValue="true"
|
||||
id="gnu.c.link.option.shared"/>
|
||||
</toolReference>
|
||||
<toolReference
|
||||
outputs="so"
|
||||
outputPrefix="lib"
|
||||
id="cdt.managedbuild.tool.gnu.cpp.linker">
|
||||
<optionReference
|
||||
defaultValue="true"
|
||||
id="gnu.cpp.link.option.shared"/>
|
||||
</toolReference>
|
||||
</target>
|
||||
<target
|
||||
|
@ -1261,10 +1288,16 @@
|
|||
<toolReference
|
||||
outputs="dll,a.dll"
|
||||
id="cdt.managedbuild.tool.gnu.c.linker">
|
||||
<optionReference
|
||||
defaultValue="true"
|
||||
id="gnu.c.link.option.shared"/>
|
||||
</toolReference>
|
||||
<toolReference
|
||||
outputs="dll,a.dll"
|
||||
id="cdt.managedbuild.tool.gnu.cpp.linker">
|
||||
<optionReference
|
||||
defaultValue="true"
|
||||
id="gnu.cpp.link.option.shared"/>
|
||||
</toolReference>
|
||||
</target>
|
||||
<target
|
||||
|
|
Loading…
Add table
Reference in a new issue