diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuild/core/tests/ManagedBuildCoreTests.java b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuild/core/tests/ManagedBuildCoreTests.java index 5b6e952c1f2..d49761a8e25 100644 --- a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuild/core/tests/ManagedBuildCoreTests.java +++ b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuild/core/tests/ManagedBuildCoreTests.java @@ -1,5 +1,5 @@ /********************************************************************** - * Copyright (c) 2004 Intel Corporation and others. + * Copyright (c) 2004, 2005 Intel Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at @@ -89,8 +89,8 @@ public class ManagedBuildCoreTests extends TestCase { String expectedSuperToolId1 = "cdt.managedbuild.tool.testgnu.c.compiler"; String expectedSuperOutputFlag1 = "-o"; String expectedSuperGetToolCommand1 = "gcc"; - String expectedSuperInputExt1 = "c"; - String expectedSuperToolInterfaceExt1 = "h"; + String[] expectedSuperInputExt1 = {"c"}; + String[] expectedSuperToolInterfaceExt1 = {"h"}; String[] expectedSuperToolOutputExt1 = {"o"}; String expectedOptionCategory1 = "testgnu.c.compiler.category.preprocessor"; String[] OptionId1 = {"testgnu.c.compiler.exe.debug.option.optimization.level", @@ -180,21 +180,11 @@ public class ManagedBuildCoreTests extends TestCase { assertEquals(tool.getId(), expectedToolId1[iconfig]); assertEquals(superTool.getId(), expectedSuperToolId1); assertEquals(tool.getNatureFilter(), expecectedCNature); - List expectedSuperInputExt1List = new ArrayList(); - String[] expectedSuperInputExt1Tokens = expectedSuperInputExt1.split(","); //$NON-NLS-1$ - for (i = 0; i < expectedSuperInputExt1Tokens.length; ++i) { - expectedSuperInputExt1List.add(expectedSuperInputExt1Tokens[i].trim()); - } - assertEquals(superTool.getInputExtensions(), expectedSuperInputExt1List); + assertTrue(Arrays.equals(superTool.getAllInputExtensions(), expectedSuperInputExt1)); assertEquals(superTool.getOutputFlag(), expectedSuperOutputFlag1); assertEquals(superTool.getToolCommand(), expectedSuperGetToolCommand1); - assertTrue(Arrays.equals(superTool.getOutputExtensions(), expectedSuperToolOutputExt1)); - List expectedSuperInterfaceExt1List = new ArrayList(); - String[] expectedSuperInterfaceExt1Tokens = expectedSuperToolInterfaceExt1.split(","); //$NON-NLS-1$ - for (i = 0; i < expectedSuperInterfaceExt1Tokens.length; ++i) { - expectedSuperInterfaceExt1List.add(expectedSuperInterfaceExt1Tokens[i].trim()); - } - assertEquals(superTool.getInterfaceExtensions(), expectedSuperInterfaceExt1List); + assertTrue(Arrays.equals(superTool.getAllDependencyExtensions(), expectedSuperToolInterfaceExt1)); + assertTrue(Arrays.equals(superTool.getOutputsAttribute(), expectedSuperToolOutputExt1)); assertTrue(superTool.isAbstract()); @@ -276,7 +266,7 @@ public class ManagedBuildCoreTests extends TestCase { String[] expectedToolOutput = {""}; String expectedSuperOutputFlag1 = "-o"; String expectedSuperGetToolCommand1 = "gcc"; - String expectedSuperInputExt1 = "o"; + String[] expectedSuperInputExt1 = {"o"}; String[] expectedSuperToolOutputExt1 = {""}; String expectedOptionCategory1 = "testgnu.c.link.category.general"; String OptionId1A = "testgnu.c.link.option.libs"; @@ -371,16 +361,11 @@ public class ManagedBuildCoreTests extends TestCase { assertEquals(superTool.getId(), expectedSuperToolId1); assertEquals(tool.getNatureFilter(), expecectedCNature); assertEquals(tool.getOutputPrefix(), expectedToolOutputPrefix); - assertTrue(Arrays.equals(superTool.getOutputExtensions(), expectedToolOutput)); - List expectedSuperInputExt1List = new ArrayList(); - String[] expectedSuperInputExt1Tokens = expectedSuperInputExt1.split(","); //$NON-NLS-1$ - for (i = 0; i < expectedSuperInputExt1Tokens.length; ++i) { - expectedSuperInputExt1List.add(expectedSuperInputExt1Tokens[i].trim()); - } - assertEquals(superTool.getInputExtensions(), expectedSuperInputExt1List); + assertTrue(Arrays.equals(superTool.getOutputsAttribute(), expectedToolOutput)); + assertTrue(Arrays.equals(superTool.getAllInputExtensions(), expectedSuperInputExt1)); assertEquals(superTool.getOutputFlag(), expectedSuperOutputFlag1); assertEquals(superTool.getToolCommand(), expectedSuperGetToolCommand1); - assertTrue(Arrays.equals(superTool.getOutputExtensions(), expectedSuperToolOutputExt1)); + assertTrue(Arrays.equals(superTool.getOutputsAttribute(), expectedSuperToolOutputExt1)); // Fetch and check an option category // @@ -476,8 +461,8 @@ public class ManagedBuildCoreTests extends TestCase { String expectedSuperToolId1 = "cdt.managedbuild.tool.testgnu.cpp.compiler"; String expectedSuperOutputFlag1 = "-o"; String expectedSuperGetToolCommand1 = "g++"; - String expectedSuperInputExt1 = "c,C,cc,cxx,cpp"; - String expectedSuperToolInterfaceExt1 = "h,H,hpp"; + String[] expectedSuperInputExt1 = {"c","C","cc","cxx","cpp"}; + String[] expectedSuperToolInterfaceExt1 = {"h","H","hpp"}; String[] expectedSuperToolOutputExt1 = {"o"}; String expectedOptionCategory1 = "testgnu.cpp.compiler.category.preprocessor"; String[] OptionId1 = {"testgnu.cpp.compiler.lib.debug.option.optimization.level", @@ -569,22 +554,11 @@ public class ManagedBuildCoreTests extends TestCase { assertEquals(tool.getId(), expectedToolId1[iconfig]); assertEquals(superTool.getId(), expectedSuperToolId1); assertEquals(tool.getNatureFilter(), expecectedCCNature); - - List expectedSuperInputExt1List = new ArrayList(); - String[] expectedSuperInputExt1Tokens = expectedSuperInputExt1.split(","); //$NON-NLS-1$ - for (i = 0; i < expectedSuperInputExt1Tokens.length; ++i) { - expectedSuperInputExt1List.add(expectedSuperInputExt1Tokens[i].trim()); - } - assertEquals(superTool.getInputExtensions(), expectedSuperInputExt1List); + assertTrue(Arrays.equals(superTool.getAllInputExtensions(), expectedSuperInputExt1)); assertEquals(superTool.getOutputFlag(), expectedSuperOutputFlag1); assertEquals(superTool.getToolCommand(), expectedSuperGetToolCommand1); - List expectedSuperInterfaceExt1List = new ArrayList(); - String[] expectedSuperInterfaceExt1Tokens = expectedSuperToolInterfaceExt1.split(","); //$NON-NLS-1$ - for (i = 0; i < expectedSuperInterfaceExt1Tokens.length; ++i) { - expectedSuperInterfaceExt1List.add(expectedSuperInterfaceExt1Tokens[i].trim()); - } - assertEquals(superTool.getInterfaceExtensions(), expectedSuperInterfaceExt1List); - assertTrue(Arrays.equals(superTool.getOutputExtensions(), expectedSuperToolOutputExt1)); + assertTrue(Arrays.equals(superTool.getAllDependencyExtensions(), expectedSuperToolInterfaceExt1)); + assertTrue(Arrays.equals(superTool.getOutputsAttribute(), expectedSuperToolOutputExt1)); // Fetch and check an option category // diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuild/core/tests/ManagedBuildCoreTests20.java b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuild/core/tests/ManagedBuildCoreTests20.java index 6c876fa55c6..b8124804171 100644 --- a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuild/core/tests/ManagedBuildCoreTests20.java +++ b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuild/core/tests/ManagedBuildCoreTests20.java @@ -1,5 +1,5 @@ /********************************************************************** - * Copyright (c) 2003 IBM Corporation and others. + * Copyright (c) 2003, 2005 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at diff --git a/build/org.eclipse.cdt.managedbuilder.core/schema/buildDefinitions.exsd b/build/org.eclipse.cdt.managedbuilder.core/schema/buildDefinitions.exsd index 86834784d9d..8cc0f1a7dcb 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/schema/buildDefinitions.exsd +++ b/build/org.eclipse.cdt.managedbuilder.core/schema/buildDefinitions.exsd @@ -188,34 +188,34 @@ - - - - Specifies the pre-build command, which runs prior to the standard MBS build. - - - - - - - Specifies the post-build command, which runs after the standard MBS build. - - - - - - - Specifies the string to be displayed when the pre-build command step is run. - - - - - - - Specifies the string to be displayed when the post-build command step is run. - - - + + + + Specifies the pre-build command, which runs prior to the standard MBS build. + + + + + + + Specifies the post-build command, which runs after the standard MBS build. + + + + + + + Specifies the string to be displayed when the pre-build command step is run. + + + + + + + Specifies the string to be displayed when the post-build command step is run. + + + @@ -294,6 +294,20 @@ + + + + Specifies the id of the Tool that creates the final build artifact (the end target of the build). + + + + + + + A semi-colon separated list of IDs of other outputTypes, besides the primary outputType of the targetTool, that are also considered to be build artifacts. + + + @@ -344,6 +358,8 @@ + + @@ -383,22 +399,31 @@ - A comma-separated list of file extensions that the tool will produce output for. + Deprecated - use the InputType element. + + + - A comma-separated list of file extensions that are used for header files. Since many other files depend on the interfaces defined in header files, the build system needs to be able to determine that a header file has changed to properly rebuild its dependents. + Deprecated - use the InputType element. + + + - The extension that the tool will produce from a given input. + Deprecated - use the OutputType element. + + + @@ -411,8 +436,11 @@ - Some tools produce files with a special prefix that must be specified. For example, a librarian on POSIX systems expects the output to be lib<target>.a, so 'lib' would be the prefix. + Deprecated - use the OutputType element. + + + @@ -442,7 +470,7 @@ - Specifies the command "pattern" that indicates how the parts of the command line are used to create the entire command line. The pattern consists of the replaceable variables command, flags, outputFlag, output, and inputs. The default pattern is ${command} ${flags} ${outputflag}${output} ${inputs} White space and other characters are significant and are copied to the generated command. + Specifies the command "pattern" that indicates how the parts of the command line are used to create the entire command line. The pattern consists of the replaceable variables command, flags, outputFlag, output, and inputs. The default pattern is ${command} ${flags} ${outputflag}${output} ${inputs}, except when customBuildStep is true, where the default is $(command). White space and other characters are significant and are copied to the generated command. @@ -459,10 +487,10 @@ - This is an optional field that specifies the class that provides the source file dependency calculation for a given tool. You can replace the default calculator with a class that implements the <code>IManagedDependencyGenerator</code> interface. + Deprecated - use the InputType element. - + @@ -473,6 +501,304 @@ + + + + Specifies whether the Tool wants the MBS to display the Advanced Input category with the Tool's property categories. This allows the user to specify input order and additional inputs. The default is false. + + + + + + + Specifies whether this Tool represents a user-define custom build step. The default is false. + + + + + + + Specifies a string that is written to the build output prior to each invocation of the tool. The default value is “Invoking tool-name (tool-id)…” + + + + + + + + + + Defines a type of input for the tool. Note that the calculated dependencies of an input type are not described by a separate input type, but are described by attributes of this element. + + + + + + + + + + + A unique identifier for the input-type that will be used by the build model. + + + + + + + The name of the input type that is displayed to the user in the UI. + + + + + + + The id of an input-type that this input-type is derived from. + + + + + + + The id of an Eclipse content type that describes this type of input. Either this attribute or the sources attribute must be specified by this element or a superclass. If both are specified, and the content type specified here is defined by Eclipse, the sources attribute is not used. + + + + + + + A comma-separated list of file extensions that identify files of this input type. Note that the user will not be able to modify the set of file extensions as they can when sourceContentType is specified. + + + + + + + The id of an Eclipse content type that describes the calculated dependencies for this type of input. If dependencyExtensions is also specified, and the content type specified here is defined by Eclipse, the dependencyExtensions attribute is not used. + + + + + + + A comma-separated list of file extensions that are used for calculated dependencies of this input-type. Note that the user will not be able to modify the set of file extensions as they can when dependencyContentType is specified. + + + + + + + The id of an Option element that is used on the command line to identify inputs of this type. The default when not specified is to assign the inputs to the ${Inputs} part of the command line. + + + + + + + Specifies whether all inputs of this type are used in one invocation of the tool. The inputs can be project resources, and the outputs of other Tools in the Tool-chain. The default is false. + + + + + + + Specifies whether this is considered the primary input of the tool. The default is false. + + + + + + + Specifies the class that provides the source file dependency calculation for this input-type. You can replace the default calculator with a class that implements the <code>IManagedDependencyGenerator</code> interface. + + + + + + + + + + A variable used in the build file to represent the input files when multipleOfType is True. The same variable name can be used in an outputType element to identify a set of output files that contribute to this tool's input. The default name is chosen by MBS. + + + + + + + + + + Describes optional, ordering, information regarding the inputs of an inputType. + + + + + + + Defines the relative or absolute path of the resource to which this element applies. The resource must be a member of the project, or the output from another tool in the tool-chain. + + + + + + + A comma-separated list of integer values that specify the input order of this resource. In most cases, a single value is used. A list is used if the same input resource appears multiple times in the input list. The order number begins at 1. All unordered input resources fill the first gap in the specified order values. + + + + + + + If True, this input resource is not used as an input to the tool. + + + + + + + + + + Describes optional information regarding additional inputs and/or dependencies. + + + + + + + Defines a semi-colon delimited list of relative or absolute paths of the resource to which this element applies. The resources must be a member of the project, the output from another tool in the tool-chain, or an external file. The file name of the path can use GNU Make pattern rule syntax in order to generate the name from the filename of the input file. + + + + + + + Defines the type of additional input, whether the resource is added to the dependency list, the inputs on the command line, or both. + + + + + + + + + + + + + + + + + + + + Defines a type of output for the tool. + + + + + + + A unique identifier for the output-type that will be used by the build model. + + + + + + + The name of the output type that is displayed to the user in the UI. + + + + + + + The id of an output-type that this output-type is derived from. + + + + + + + The id of an Eclipse content type that describes this type of output. Either this attribute or the outputs attribute must be specified by this element or a superclass. If both are specified, and the content type specified here is defined by Eclipse, the outputs attribute is not used. + + + + + + + A comma-separated list of file extensions that identify files of this output type. Note that the user will not be able to modify the set of file extensions as they can when outputContentType is specified. + + + + + + + The id of an Option element that is used on the command line to identify outputs of this type. The default is to use the Tool outputFlag attribute if primaryOutput is True. If primaryOutput is False, the default is to not add the output(s) to the command line. If specified, the nameProvider, namePattern and outputNames are ignored. + + + + + + + Specifies whether multiple outputs of this type are created by one invocation of the tool. The default is False. If True, the nameProvider attribute or outputNames attribute must be specified. + + + + + + + The id of the input-type that this output-type is created from. It is used in determining the build "rules" for the output-type, and for the default name of the output file. + + + + + + + Specifies whether this is the primary output of the tool. The default is False. + + + + + + + Some tools produce files with a special prefix that must be specified. For example, a librarian on POSIX systems expects the output to be libtarget.a, so 'lib' would be the prefix. + + + + + + + A semi-colon delimited list of the complete set of output file names generated for this outputType. If specified, the namePattern is ignored. + + + + + + + Specifies a pattern, using the Gnu Make pattern rule syntax, for deriving the output resource name from the input resource name. The default is to use the input resource base name with the first output extension. + + + + + + + The name of the class that implements the <code>IManagedOutputNameProvider</code> interface. If specified, the outputNames and namePattern are ignored. This attribute must be specified when multipleOfType is True. + + + + + + + + + + A variable used in the build file to represent the output file(s). The same variable name can be used in an inputType element to identify a set of output files that contribute to a tool's input. The default name is chosen by MBS. + + + @@ -580,8 +906,8 @@ - General options can be one of the following types; 'string' for catch-all entries for options that cannot be easily defined any other way, 'string list' for entries that consist of a list of values such as defined symbols or paths, 'boolean' for options that have two values, and 'enumerated' for options that are one-of a list of values. - + General options can be one of the following types; 'string' for catch-all entries for options that cannot be easily defined any other way, 'string list' for entries that consist of a list of values such as defined symbols or paths, 'boolean' for options that have two values, and 'enumerated' for options that are one-of a list of values. + Additional special types exist to flag options of special relevance to the build model; 'include', 'libs', 'userObjs' and 'definedSymbols'. You can pre-populate with optionValues, and they will display in the UI the same way the 'stringList' options do. The build model will look specifically for these value types when clients query for include paths and preprocessor defines. The makefile generator will treat the libs and userObjs entries differently than other stringLists. @@ -905,14 +1231,14 @@ Additional special types exist to flag options of special relevance to the build - <p> -Version identifier for the managed build extension point. It is a string representation, consisting of three (3) tokens separated by a decimal point. The 3 tokens are positive integer numbers. For example, the following are valid version identifiers: - <ul> - <li><code>0.0.0</code></li> - <li><code>1.0.1234</code></li> - <li><code>1.9</code> (interpreted as <code>1.9.0</code>)</li> - <li><code>3</code> (interpreted as <code>3.0.0</code>)</li> - </ul> + <p> +Version identifier for the managed build extension point. It is a string representation, consisting of three (3) tokens separated by a decimal point. The 3 tokens are positive integer numbers. For example, the following are valid version identifiers: + <ul> + <li><code>0.0.0</code></li> + <li><code>1.0.1234</code></li> + <li><code>1.9</code> (interpreted as <code>1.9.0</code>)</li> + <li><code>3</code> (interpreted as <code>3.0.0</code>)</li> + </ul> </p> @@ -941,14 +1267,14 @@ Version identifier for the managed build extension point. It is a string represe - The following is an example of the extension point usage: -<p> -<pre> - <extension - id="buildExample" - name="Definitions for Build Example" - point="org.eclipse.cdt.managedbuilder.core.buildDefinitions"> - etc... + The following is an example of the extension point usage: +<p> +<pre> + <extension + id="buildExample" + name="Definitions for Build Example" + point="org.eclipse.cdt.managedbuilder.core.buildDefinitions"> + etc... </pre> @@ -976,7 +1302,7 @@ Version identifier for the managed build extension point. It is a string represe - Copyright (c) 2003, 2004 IBM Corporation and others. + Copyright (c) 2003, 2005 IBM Corporation and others. All rights reserved. This program and the accompanying materials are made available under the terms of the Common Public License v1.0 which accompanies this distribution, and is available on the <a href="http://www.eclipse.org/legal/cpl-v10.html"> Eclipse</a> website. diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IAdditionalInput.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IAdditionalInput.java new file mode 100644 index 00000000000..62b0050d647 --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IAdditionalInput.java @@ -0,0 +1,89 @@ +/********************************************************************** + * Copyright (c) 2005 Intel Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Intel Corporation - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.managedbuilder.core; + +/** + * This interface represents an additionalInput instance in the managed build system. + * This element is only present if the user or a tool integrator needs to define + * additional inputs or dependencies to a tool. An inputType element can have + * multiple additionalInput children. + * + * @since 3.0 + */ +public interface IAdditionalInput { + + // Schema attribute names for additionalInput elements + public static final String ADDITIONAL_INPUT_ELEMENT_NAME = "additionalInput"; //$NON-NLS-1$ + public static final String PATHS = "paths"; //$NON-NLS-1$ + public static final String KIND = "kind"; //$NON-NLS-1$ + public static final String ADDITIONAL_DEPENDENCY = "additionaldependency"; //$NON-NLS-1$ + public static final int KIND_ADDITIONAL_DEPENDENCY = 1; + public static final String ADDITIONAL_INPUT = "additionalinput"; //$NON-NLS-1$ + public static final int KIND_ADDITIONAL_INPUT = 2; + public static final String ADDITIONAL_INPUT_DEPENDENCY = "additionalinputdependency"; //$NON-NLS-1$ + public static final int KIND_ADDITIONAL_INPUT_DEPENDENCY = 3; + + /** + * Returns the InputType parent of this AdditionalInput. + * + * @return IInputType + */ + public IInputType getParent(); + + /** + * Returns a semi-colon separated list of the relative or absolute paths of the resources + * to which this element applies. + * The resources must be a member of the project, the output from another tool in the + * tool-chain, or an external file. The file name of the path can use GNU Make pattern + * rule syntax (in order to generate the name from the input file name). + * + * @return String + */ + public String getPaths(); + + /** + * Sets semi-colon separated list of the relative or absolute paths of the resources to + * which this element applies. + * + * @param paths + */ + public void setPaths(String paths); + + /** + * Returns the kind of additional input. The valid values are: + * KIND_ADDITIONAL_DEPENDENCY added as a tool dependency, but not to the command line. + * KIND_ADDITIONAL_INPUT added as an additional input to the command line, but not as a dependency. + * KIND_ADDITIONAL_INPUT_DEPENDENCY added as both. + * The default is KIND_ADDITIONAL_INPUT_DEPENDENCY + */ + public int getKind(); + + /** + * Sets the kind of additional input. + */ + public void setKind(int kind); + + /** + * Returns true if this element has changes that need to + * be saved in the project file, else false. + * + * @return boolean + */ + public boolean isDirty(); + + /** + * Sets the element's "dirty" (have I been modified?) flag. + * + * @param isDirty + */ + public void setDirty(boolean isDirty); + +} diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IConfiguration.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IConfiguration.java index a4cb16687bd..a11e0b82904 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IConfiguration.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IConfiguration.java @@ -224,6 +224,13 @@ public interface IConfiguration extends IBuildObject { */ public ITool[] getTools(); + /** + * Returns the tool in this configuration that creates the build artifact. + * + * @return ITool + */ + public ITool getTargetTool(); + /** * Returns true if this configuration has overridden the default build * build command in this configuration, otherwise false. diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IInputOrder.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IInputOrder.java new file mode 100644 index 00000000000..32fca503bde --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IInputOrder.java @@ -0,0 +1,101 @@ +/********************************************************************** + * Copyright (c) 2005 Intel Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Intel Corporation - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.managedbuilder.core; + +/** + * This interface represents an inputOrder instance in the managed build system. + * This element is only present if the user or a tool integrator needs to define + * the specific order of input files to a tool, or needs to exclude one or more + * input files from being used by a tool. An inputType element can have + * multiple inputOrder children. + * + * @since 3.0 + */ +public interface IInputOrder { + public static final String INPUT_ORDER_ELEMENT_NAME = "inputOrder"; //$NON-NLS-1$ + public static final String PATH = "path"; //$NON-NLS-1$ + public static final String ORDER = "order"; //$NON-NLS-1$ + public static final String EXCLUDED = "excluded"; //$NON-NLS-1$ + + /** + * Returns the InputType parent of this InputOrder. + * + * @return IInputType + */ + public IInputType getParent(); + + /** + * Returns the relative or absolute path of the resource to which this element applies. + * The resource must be a member of the project, or the output from another tool in the + * tool-chain. + * + * @return String + */ + public String getPath(); + + /** + * Sets the relative or absolute path of the resource to which this element applies. + * + * @param path + */ + public void setPath(String path); + + /** + * Returns a comma-separated list of integer values that specify the order of this resource. + * In most cases, only a single integer value will be specified. A list is supported + * for the case where a single input file needs to be specified multiple times on the + * command line. The order numbers begin at 1. Not all values need to be specified. + * Unordered resources will fill the first gap. For example: + * To specify the first input file, use 1. + * To specify the last input file, without specifying an order for any other input file, use 2. + * To specify only the first two input files and last input file, use 1, 2 & 4. + * + * @return String + */ + public String getOrder(); + + /** + * Sets the comma-separated list of integer values that specify the order of this resource. + * + * @param order + */ + public void setOrder(String order); + + /** + * Returns true if this resource is not used as an input for the tool. + * + * @return boolean + */ + public boolean getExcluded(); + + /** + * Sets whether this resource is not used as an input for the tool. + * + * @param excluded + */ + public void setExcluded(boolean excluded); + + /** + * Returns true if this element has changes that need to + * be saved in the project file, else false. + * + * @return boolean + */ + public boolean isDirty(); + + /** + * Sets the element's "dirty" (have I been modified?) flag. + * + * @param isDirty + */ + public void setDirty(boolean isDirty); + +} diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IInputType.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IInputType.java new file mode 100644 index 00000000000..32280ef8aa3 --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IInputType.java @@ -0,0 +1,373 @@ +/********************************************************************** + * Copyright (c) 2005 Intel Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Intel Corporation - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.managedbuilder.core; + +import org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyGenerator; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.core.runtime.IPath; + +/** + * This interface represents an inputType instance in the managed build system. + * It describes one category of input files to a Tool. A tool can have + * multiple inputType children. + * + * @since 3.0 + */ +public interface IInputType extends IBuildObject { + public static final String INPUT_TYPE_ELEMENT_NAME = "inputType"; //$NON-NLS-1$ + public static final String SOURCE_CONTENT_TYPE = "sourceContentType"; //$NON-NLS-1$ + public static final String SOURCES = "sources"; //$NON-NLS-1$ + public static final String DEPENDENCY_CONTENT_TYPE = "dependencyContentType"; //$NON-NLS-1$ + public static final String DEPENDENCY_EXTENSIONS = "dependencyExtensions"; //$NON-NLS-1$ + public static final String OPTION = "option"; //$NON-NLS-1$ + public static final String MULTIPLE_OF_TYPE = "multipleOfType"; //$NON-NLS-1$ + public static final String PRIMARY_INPUT = "primaryInput"; //$NON-NLS-1$ + public static final String BUILD_VARIABLE = "buildVariable"; //$NON-NLS-1$ + + /** + * Creates an inputOrder child for this InputType. + * + * @param path The path associated with the InputOrder element + * @return IInputOrder of the new element + */ + public IInputOrder createInputOrder(String path); + + /** + * Removes the InputOrder element with the path specified in the argument. + * + * @param path The path associated with the InputOrder element + */ + public void removeInputOrder(String path); + + /** + * Removes the InputOrder element specified in the argument. + * + * @param path The InputOrder element + */ + public void removeInputOrder(IInputOrder element); + + /** + * Returns all of the InputOrder children of this InputType + * + * @return IInputOrder[] + */ + public IInputOrder[] getInputOrders(); + + /** + * Returns the InputOrder element with the path specified in the argument. + * + * @param path The path associated with the InputOrder element + * @return IInputOrder + */ + public IInputOrder getInputOrder(String path); + + /** + * Creates an additionalInput child for this InputType. + * + * @param path The path associated with the AdditionalInput element + * @return IAdditionalInput of the new element + */ + public IAdditionalInput createAdditionalInput(String path); + + /** + * Removes the AdditionalInput element with the path specified in the argument. + * + * @param path The path associated with the AdditionalInput element + */ + public void removeAdditionalInput(String path); + + /** + * Removes the AdditionalInput element specified in the argument. + * + * @param element The AdditionalInput element + */ + public void removeAdditionalInput(IAdditionalInput element); + + /** + * Returns all of the AdditionalInput children of this InputType + * + * @return IAdditionalInput[] + */ + public IAdditionalInput[] getAdditionalInputs(); + + /** + * Returns the AdditionalInput element with the path specified in the argument. + * + * @param path The path associated with the AdditionalInput element + * @return IAdditionalInput + */ + public IAdditionalInput getAdditionalInput(String path); + + /** + * Returns all of the additional input resources of this InputType. + * Note: This does not include additional dependencies. + * + * @return IPath[] + */ + public IPath[] getAdditionalResources(); + + /** + * Returns all of the additional dependency resources of this InputType. + * Note: This does not include additional inputs. + * + * @return IPath[] + */ + public IPath[] getAdditionalDependencies(); + + /** + * Returns the tool parent of this InputType. + * + * @return ITool + */ + public ITool getParent(); + + /** + * Returns the IInputType that is the superclass of this + * InputType, or null if the attribute was not specified. + * + * @return IInputType + */ + public IInputType getSuperClass(); + + /** + * Returns the Eclipse IContentType that describes this + * input type. If both the sources attribute and the sourceContentType + * attribute are specified, the sourceContentType will be used if it + * is registered in Eclipse. + * + * @return IContentType + */ + public IContentType getSourceContentType(); + + /** + * Sets the Eclipse IContentType that describes this + * input type. + * + * @param contentType The Eclipse content type + */ + public void setSourceContentType(IContentType contentType); + + /** + * Returns the list of valid source extensions from the + * sourceExtensions attribute. Note that this value is not used + * if source content type is specified and registered with Eclipse. + * Also, the user will not be able to modify the set of file + * extensions as they can when sourceContentType is specified. + * + * @return String[] + */ + public String[] getSourceExtensionsAttribute(); + + /** + * Sets the list of valid source extensions for this input type. + * NOTE: The value of this attribute will NOT be used if a + * source content type is specified and is registered with + * Eclipse. + * + * @param extensions The comma-separated list of valid file extensions + * - not including the separator period. + */ + public void setSourceExtensionsAttribute(String extensions); + + /** + * Returns the list of valid source extensions for this input type. + * Note that the list will come from the sourceContentType if it + * is specified and registered with Eclipse. Otherwise the + * sourceExtensions attribute will be used. + * + * @return String[] + */ + public String[] getSourceExtensions(); + + /** + * Answers true if the input type considers the file extension to be + * one associated with a source file. + * + * @param ext file extension of the source + * @return boolean + */ + public boolean isSourceExtension(String ext); + + /** + * Returns the Eclipse IContentType that describes the + * dependency files of this input type. If both the dependencyExtensions + * attribute and the dependencyContentType attribute are specified, + * the dependencyContentType will be used if it is defined in Eclipse. + * + * @return IContentType + */ + public IContentType getDependencyContentType(); + + /** + * Sets the Eclipse IContentType that describes the + * dependency files of this input type. + * + * @return type + */ + public void setDependencyContentType(IContentType type); + + /** + * Returns the list of valid dependency extensions from the + * dependencyExtensions attribute. Note that this value is not used + * if dependency content type is specified and registered with Eclipse. + * Also, the user will not be able to modify the set of file + * extensions as they can when dependencyContentType is specified. + * + * @return String[] + */ + public String[] getDependencyExtensionsAttribute(); + + /** + * Sets the list of valid dependency extensions for this input type. + * NOTE: The value of this attribute will NOT be used if a + * dependency content type is specified and is registered with + * Eclipse. + * + * @param extensions The comma-separated list of valid dependency extensions + * - not including the separator period. + */ + public void setDependencyExtensionsAttribute(String extensions); + + /** + * Returns the list of valid dependency extensions for this input type. + * Note that the list will come from the dependencyContentType if it + * is specified and registered with Eclipse. Otherwise the + * dependencyExtensions attribute will be used. + * + * @return String[] + */ + public String[] getDependencyExtensions(); + + /** + * Answers true if the input type considers the file extension to be + * one associated with a dependency file. + * + * @param ext file extension of the source + * @return boolean + */ + public boolean isDependencyExtension(String ext); + + /** + * Returns the id of the option that is associated with this + * input type on the command line. The default is to not use a command + * line option and to assign this input to the ${Inputs} part of the command line. + * + * @return String + */ + public String getOptionId(); + + /** + * Sets the id of the option that is associated with this + * input type on the command line. + * + * @param optionId + */ + public void setOptionId(String optionId); + + /** + * Returns true if this inputType can contain multiple input + * resources, else false. The inputs can be project resources, + * or the outputs of other tools in the tool-chain. + * + * @return boolean + */ + public boolean getMultipleOfType(); + + /** + * Sets whether this inputType can contain multiple input resources + * + * @param multiple + */ + public void setMultipleOfType(boolean multiple); + + /** + * Returns true if this inputType is considered the primary input + * of the tool, else false. + * + * @return boolean + */ + public boolean getPrimaryInput(); + + /** + * Sets whether this inputType is considered the primary input of the tool + * + * @param primary + */ + public void setPrimaryInput(boolean primary); + + /** + * Returns the plugin.xml element of the dependencyGenerator extension or null if none. + * + * @return IConfigurationElement + */ + public IConfigurationElement getDependencyGeneratorElement(); + + /** + * Sets the DependencyGenerator plugin.xml element + * + * @param element + */ + public void setDependencyGeneratorElement(IConfigurationElement element); + + /** + * Returns a class instance that implements an interface to generate + * source-level dependencies for this input type. + * This method may return null in which case, the receiver + * should assume that the input type does not require dependency information + * when the project is built. + * + * @return IManagedDependencyGenerator + */ + public IManagedDependencyGenerator getDependencyGenerator(); + + /** + * Returns the name of the build variable associated this this input type's resources + * The build variable used in the build file to represent the list of input files when + * multipleOfType is True. The same variable name can be used by an outputType to + * identify a set of output files that contribute to this tools input + * (i.e., those using the same buildVariable name). The default name is chosen by MBS. + * + * @return String + */ + public String getBuildVariable(); + + /** + * Sets the name of the build variable associated this this input type's resources + * + * @return variableName + */ + public void setBuildVariable(String variableName); + + /** + * Returns true if this element has changes that need to + * be saved in the project file, else false. + * + * @return boolean + */ + public boolean isDirty(); + + /** + * Returns true if this InputType was loaded from a manifest file, + * and false if it was loaded from a project (.cdtbuild) file. + * + * @return boolean + */ + public boolean isExtensionElement(); + + /** + * Sets the element's "dirty" (have I been modified?) flag. + * + * @param isDirty + */ + public void setDirty(boolean isDirty); + +} diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IManagedBuildInfo.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IManagedBuildInfo.java index 7384fd6a09b..7e0303d843f 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IManagedBuildInfo.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IManagedBuildInfo.java @@ -1,5 +1,5 @@ /********************************************************************** - * Copyright (c) 2003,2005 Rational Software Corporation and others. + * Copyright (c) 2003, 2005 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 @@ -250,9 +250,9 @@ public interface IManagedBuildInfo { /** * Returns a String containing the command-line invocation - * for the tool associated with the extension. + * for the tool associated with the output extension. * - * @param extension the file extension of the build goal + * @param extension the file extension of the output file * @return a String containing the command line invocation for the tool */ public String getToolForConfiguration(String extension); @@ -266,6 +266,24 @@ public interface IManagedBuildInfo { */ public String getToolForSource(String sourceExtension); + /** + * Returns a ITool for the tool associated with the + * input extension. + * + * @param extension the file extension of the input file + * @return ITool + */ + public ITool getToolFromInputExtension(String extension); + + /** + * Returns a ITool for the tool associated with the + * output extension. + * + * @param extension the file extension of the output file + * @return ITool + */ + public ITool getToolFromOutputExtension(String extension); + /** * Answers a String array containing the contents of the * user objects option, if one is defined for the target. diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IManagedOutputNameProvider.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IManagedOutputNameProvider.java new file mode 100644 index 00000000000..77a6b075ace --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IManagedOutputNameProvider.java @@ -0,0 +1,23 @@ +/********************************************************************** + * Copyright (c) 2005 Intel Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Intel Corporation - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.managedbuilder.core; + +import org.eclipse.core.runtime.IPath; + +public interface IManagedOutputNameProvider { + /** + * + * @param tool + * @param primaryInputNames + * @return IPath[] + */ + public IPath[] getOutputNames( ITool tool, IPath[] primaryInputNames ); +} diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IOutputType.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IOutputType.java new file mode 100644 index 00000000000..470042d5bb5 --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IOutputType.java @@ -0,0 +1,288 @@ +/********************************************************************** + * Copyright (c) 2005 Intel Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Intel Corporation - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.managedbuilder.core; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.content.IContentType; + +/** + * This interface represents an outputType instance in the managed build system. + * It describes one category of output files created by a Tool. A tool can + * have multiple outputType children. + * + * @since 3.0 + */ +public interface IOutputType extends IBuildObject { + public static final String OUTPUT_TYPE_ELEMENT_NAME = "outputType"; //$NON-NLS-1$ + public static final String OUTPUT_CONTENT_TYPE = "outputContentType"; //$NON-NLS-1$ + public static final String OUTPUTS = "outputs"; //$NON-NLS-1$ + public static final String OPTION = "option"; //$NON-NLS-1$ + public static final String MULTIPLE_OF_TYPE = "multipleOfType"; //$NON-NLS-1$ + public static final String PRIMARY_INPUT_TYPE = "primaryInputType"; //$NON-NLS-1$ + public static final String PRIMARY_OUTPUT = "primaryOutput"; //$NON-NLS-1$ + public static final String OUTPUT_PREFIX = "outputPrefix"; //$NON-NLS-1$ + public static final String OUTPUT_NAMES = "outputNames"; //$NON-NLS-1$ + public static final String NAME_PATTERN = "namePattern"; //$NON-NLS-1$ + public static final String NAME_PROVIDER = "nameProvider"; //$NON-NLS-1$ + public static final String BUILD_VARIABLE = "buildVariable"; //$NON-NLS-1$ + + /** + * Returns the tool defining this OutputType. + * + * @return ITool + */ + public ITool getParent(); + + /** + * Returns the IOutputType that is the superclass of this + * OutputType, or null if the attribute was not specified. + * + * @return IInputType + */ + public IOutputType getSuperClass(); + + /** + * Returns the Eclipse IContentType that describes this + * output type. If both the outputs attribute and the outputContentType + * attribute are specified, the outputContentType will be used if it + * is defined in Eclipse. + * + * @return IContentType + */ + public IContentType getOutputContentType(); + + /** + * Sets the Eclipse IContentType that describes this + * output type. + * + * @param contentType The Eclipse content type + */ + public void setOutputContentType(IContentType contentType); + + /** + * Returns the list of valid output extensions from the + * outputs attribute. Note that this value is not used + * if output content type is specified and registered with Eclipse. + * Also, the user will not be able to modify the set of file + * extensions as they can when outputContentType is specified. + * + * @return String[] of extensions + */ + public String[] getOutputExtensionsAttribute(); + + /** + * Sets all of the output extensions that the receiver can build. + * NOTE: The value of this attribute will NOT be used if a + * output content type is specified and is registered with + * Eclipse. + * + * @param String + */ + public void setOutputExtensionsAttribute(String extensions); + + /** + * Returns the list of the output extensions that the receiver can build. + * Note that the list will come from the outputContentType if it + * is specified and registered with Eclipse. Otherwise the + * outputs attribute will be used. + * + * @return String[] + */ + public String[] getOutputExtensions(); + + /** + * Answers true if the output type considers the file extension to be + * one associated with an output file. + * + * @param ext file extension + * @return boolean + */ + public boolean isOutputExtension(String ext); + + /** + * Returns the id of the option that is associated with this + * output type on the command line. The default is to use the Tool + * outputFlag attribute if primaryOutput is True. If option is not + * specified, and primaryOutput is False, then the output file(s) of + * this outputType are not added to the command line. + * When specified, the namePattern, nameProvider and outputNames are ignored. + * + * @return String + */ + public String getOptionId(); + + /** + * Sets the id of the option that is associated with this + * output type on the command line. + * + * @param optionId + */ + public void setOptionId(String optionId); + + /** + * Returns true if this outputType creates multiple output + * resources in one invocation of the tool, else false. + * + * @return boolean + */ + public boolean getMultipleOfType(); + + /** + * Sets whether this outputType can create multiple output resources in + * one invocation of the tool. + * + * @param multiple + */ + public void setMultipleOfType(boolean multiple); + + /** + * Returns the input type that is used in determining the default + * names of this output type. + * + * @return IInputType + */ + public IInputType getPrimaryInputType(); + + /** + * Sets the input type that is used in determining the default + * names of this output type. + * + * @param inputType + */ + public void setPrimaryInputType(IInputType contentType); + + /** + * Returns true if this is considered the primary output + * of the tool, else false. + * + * @return boolean + */ + public boolean getPrimaryOutput(); + + /** + * Sets whether this is the primary output of the tool. + * + * @param primary + */ + public void setPrimaryOutput(boolean primary); + + /** + * Returns the prefix that the tool should prepend to the name of the build artifact. + * For example, a librarian usually prepends 'lib' to the target.a + * @return String + */ + public String getOutputPrefix(); + + /** + * Sets the prefix that the tool should prepend to the name of the build artifact. + * For example, a librarian usually prepends 'lib' to the target.a + * @param String + */ + public void setOutputPrefix(String prefix); + + /** + * Returns the paths of the complete set of output files for this outputType + * + * @return String + */ + public String getOutputNames(); + + /** + * Sets the complete set of output files for this outputType + * + * @param names + */ + public void getOutputNames(String names); + + /** + * Returns the pattern, using the Gnu pattern rule syntax, for deriving the + * output resource name from the input resource name. The default is to use + * the input file base filename with the output extension. + * + * @return String + */ + public String getNamePattern(); + + /** + * Sets the pattern, using the Gnu pattern rule syntax, for deriving the + * output resource name from the input resource name. + * + * @return pattern + */ + public void setNamePattern(String pattern); + + /** + * Returns the plugin.xml element of the nameProvider extension or null if none. + * nameProvider specified the name of a class that implements the IManagedOutputNameProvider + * interface. When specified, the namePattern and outputNames are ignored. + * When multipleOfType is true, this attribute, or the outputNames attribute, + * is required in order for MBS to know the names of the output files. + * + * @return IConfigurationElement + */ + public IConfigurationElement getNameProviderElement(); + + /** + * Sets the nameProvider plugin.xml element + * + * @param element + */ + public void setNameProviderElement(IConfigurationElement element); + + /** + * Returns the IManagedOutputNameProvider interface as specified by the nameProvider attribute. + * + * @return IManagedOutputNameProvider + */ + public IManagedOutputNameProvider getNameProvider(); + + /** + * Returns the name of the build variable associated this this output type's resources + * The variable is used in the build file to represent the list of output files. + * The same variable name can be used by an inputType to identify a set of output + * files that contribute to the tools input (i.e., those using the same buildVariable + * name). The default name is chosen by MBS. + * + * @return String + */ + public String getBuildVariable(); + + /** + * Sets the name of the build variable associated this this output type's resources. + * + * @return variableName + */ + public void setBuildVariable(String variableName); + + /** + * Returns true if this element has changes that need to + * be saved in the project file, else false. + * + * @return boolean + */ + public boolean isDirty(); + + /** + * Returns true if this OutputType was loaded from a manifest file, + * and false if it was loaded from a project (.cdtbuild) file. + * + * @return boolean + */ + public boolean isExtensionElement(); + + /** + * Sets the element's "dirty" (have I been modified?) flag. + * + * @param isDirty + */ + public void setDirty(boolean isDirty); + +} diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ITool.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ITool.java index 42a295f1499..13f09d5db74 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ITool.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ITool.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2004 IBM Corporation and others. + * Copyright (c) 2003, 2005 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at @@ -13,11 +13,12 @@ package org.eclipse.cdt.managedbuilder.core; import java.util.List; import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IPath; import org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyGenerator; /** - * This class represents a utility of some sort that is used in the build process. + * This interface represents a utility of some sort that is used in the build process. * A tool will generally process one or more resources to produce output resources. * Most tools have a set of options that can be used to modify the behavior of the tool. */ @@ -33,9 +34,14 @@ public interface ITool extends IBuildObject { public static final String OPTION_CAT = "optionCategory"; //$NON-NLS-1$ public static final String OPTION_REF = "optionReference"; //$NON-NLS-1$ public static final String OUTPUT_FLAG = "outputFlag"; //$NON-NLS-1$ + public static final String INPUT_TYPE = "inputType"; //$NON-NLS-1$ + public static final String OUTPUT_TYPE = "outputType"; //$NON-NLS-1$ public static final String OUTPUT_PREFIX = "outputPrefix"; //$NON-NLS-1$ public static final String OUTPUTS = "outputs"; //$NON-NLS-1$ public static final String SOURCES = "sources"; //$NON-NLS-1$ + public static final String ADVANCED_INPUT_CATEGORY = "advancedInputCategory"; //$NON-NLS-1$ + public static final String CUSTOM_BUILD_STEP = "customBuildStep"; //$NON-NLS-1$ + public static final String ANNOUNCEMENT = "announcement"; //$NON-NLS-1$ public static final String TOOL_ELEMENT_NAME = "tool"; //$NON-NLS-1$ public static final String WHITE_SPACE = " "; //$NON-NLS-1$ @@ -104,6 +110,165 @@ public interface ITool extends IBuildObject { */ public IOption[] getOptions(); + /** + * Creates a child InputType for this tool. + * + * @param InputType The superClass, if any + * @param String The id for the new InputType + * @param String The name for the new InputType + * @param boolean Indicates whether this is an extension element or a managed project element + * + * @return IInputType + * @since 3.0 + */ + public IInputType createInputType(IInputType superClass, String Id, String name, boolean isExtensionElement); + + /** + * Removes an InputType from the tool's list. + * + * @param type + * @since 3.0 + */ + public void removeInputType(IInputType type); + + /** + * Returns the complete list of input types that are available for this tool. + * The list is a merging of the input types specified for this tool with the + * input types of its superclasses. The lowest input type instance in the hierarchy + * takes precedence. + * + * @return IInputType[] + * @since 3.0 + */ + public IInputType[] getInputTypes(); + + /** + * Returns the IInputType in the tool with the specified + * ID. This is an efficient search in the receiver. + * + *

If the receiver does not have an InputType with that ID, the method + * returns null. It is the responsibility of the caller to + * verify the return value. + * + * @param id unique identifier of the InputType to search for + * @return IInputType + * @since 3.0 + */ + public IInputType getInputTypeById(String id); + + /** + * Returns the IInputType in the tool that uses the + * specified extension. + * + *

If the receiver does not have an InputType that uses the extension, + * the method returns null. It is the responsibility of the + * caller to verify the return value. + * + * @param inputExtension File extension + * @return IInputType + * @since 3.0 + */ + public IInputType getInputType(String inputExtension); + + /** + * Returns the primary IInputType in this tool + * + *

If the receiver has no InputTypes, + * the method returns null. It is the responsibility of the + * caller to verify the return value. + * + * @return IInputType + * @since 3.0 + */ + public IInputType getPrimaryInputType(); + + /** + * Returns all of the additional input resources of all InputType children. + * Note: This does not include additional dependencies. + * + * @return IPath[] + */ + public IPath[] getAdditionalResources(); + + /** + * Returns all of the additional dependency resources of all InputType children. + * Note: This does not include additional inputs. + * + * @return IPath[] + */ + public IPath[] getAdditionalDependencies(); + + /** + * Creates a child OutputType for this tool. + * + * @param OutputType The superClass, if any + * @param String The id for the new OutputType + * @param String The name for the new OutputType + * @param boolean Indicates whether this is an extension element or a managed project element + * + * @return IOutputType + * @since 3.0 + */ + public IOutputType createOutputType(IOutputType superClass, String Id, String name, boolean isExtensionElement); + + /** + * Removes an OutputType from the tool's list. + * + * @param type + * @since 3.0 + */ + public void removeOutputType(IOutputType type); + + /** + * Returns the complete list of output types that are available for this tool. + * The list is a merging of the output types specified for this tool with the + * output types of its superclasses. The lowest output type instance in the hierarchy + * takes precedence. + * + * @return IOutputType[] + * @since 3.0 + */ + public IOutputType[] getOutputTypes(); + /** + * Get the IOutputType in the receiver with the specified + * ID. This is an efficient search in the receiver. + * + *

If the receiver does not have an OutputType with that ID, the method + * returns null. It is the responsibility of the caller to + * verify the return value. + * + * @param id unique identifier of the OutputType to search for + * @return IOutputType + * @since 3.0 + */ + public IOutputType getOutputTypeById(String id); + + /** + * Returns the IOutputType in the tool that creates the + * specified extension. + * + *

If the receiver does not have an OutputType that creates the extension, + * the method returns null. It is the responsibility of the + * caller to verify the return value. + * + * @param outputExtension File extension + * @return IOutputType + * @since 3.0 + */ + public IOutputType getOutputType(String outputExtension); + + /** + * Returns the primary IOutputType in this tool + * + *

If the receiver has no OutputTypes, + * the method returns null. It is the responsibility of the + * caller to verify the return value. + * + * @return IOutputType + * @since 3.0 + */ + public IOutputType getPrimaryOutputType(); + /** * Returns the ITool that is the superclass of this * tool, or null if the attribute was not specified. @@ -162,14 +327,48 @@ public interface ITool extends IBuildObject { * The list may be empty but will never be null. * * @return List + * @deprecated - use getPrimaryInputExtensions or getAllInputExtensions */ public List getInputExtensions(); + /** + * Returns the array of valid primary source extensions this tool knows how to build. + * The array may be empty but will never be null. + * + * @return String[] + */ + public String[] getPrimaryInputExtensions(); + + /** + * Returns the array of all valid source extensions this tool knows how to build. + * The array may be empty but will never be null. + * + * @return String[] + */ + public String[] getAllInputExtensions(); + + /** + * Returns the default input extension for the primary input of the tool + * + * @return String + */ + public String getDefaultInputExtension(); + + /** + * Returns the array of all valid dependency extensions for this tool's inputs. + * The array may be empty but will never be null. + * + * @return String[] + */ + public String[] getAllDependencyExtensions(); + /** * Returns the list of valid header extensions for this tool. + * Returns the value of the headerExtensions attribute * The list may be empty but will never be null. * * @return List + * @deprecated - use getDependency* methods */ public List getInterfaceExtensions(); @@ -192,12 +391,30 @@ public interface ITool extends IBuildObject { */ public int getNatureFilter(); + /** + * Returns the array of all valid output extensions this tool can create. + * The array may be empty but will never be null. + * + * @return String[] + */ + public String[] getAllOutputExtensions(); + /** * Answers all of the output extensions that the receiver can build. + * This routine returns the value if the outputs attribute. + * + * @return String[] of extensions + * @deprecated - use getAllOutputExtensions + */ + public String[] getOutputExtensions(); + + /** + * Answers all of the output extensions that the receiver can build, + * from the value of the outputs attribute * * @return String[] of extensions */ - public String[] getOutputExtensions(); + public String[] getOutputsAttribute(); /** * Answer the output extension the receiver will create from the input, @@ -209,11 +426,13 @@ public interface ITool extends IBuildObject { public String getOutputExtension(String inputExtension); /** - * Sets all of the output extensions that the receiver can build. + * Sets all of the output extensions that the receiver can build, + * into the outputs attribute. Note that the outputs attribute is + * ignored when one or more outputTypes are specified. * * @param String */ - public void setOutputExtensions(String extensions); + public void setOutputsAttribute(String extensions); /** * Answers the argument that must be passed to a specific tool in order to @@ -247,6 +466,51 @@ public interface ITool extends IBuildObject { */ public void setOutputPrefix(String prefix); + /** + * Returns true if the Tool wants the MBS to display the Advanced + * Input category that allows the user to specify additional input resources and + * dependencies, else false. + * + * @return boolean + */ + public boolean getAdvancedInputCategory(); + + /** + * Sets whether the Tool wants the MBS to display the Advanced + * Input category that allows the user to specify additional input resources and + * dependencies. + * + * @param display + */ + public void setAdvancedInputCategory(boolean display); + + /** + * Returns true if the Tool represents a user-define custom build + * step, else false. + * + * @return boolean + */ + public boolean getCustomBuildStep(); + + /** + * Sets whether the Tool represents a user-define custom build step. + * + * @param customBuildStep + */ + public void setCustomBuildStep(boolean customBuildStep); + + /** + * Returns the announcement string for this tool + * @return String + */ + public String getAnnouncement(); + + /** + * Sets the announcement string for this tool + * @param announcement + */ + public void setAnnouncement(String announcement); + /** * Answers the command-line invocation defined for the receiver. * @@ -299,13 +563,23 @@ public interface ITool extends IBuildObject { * Returns the plugin.xml element of the dependencyGenerator extension or null if none. * * @return IConfigurationElement + * @deprecated - use getDependencyGeneratorElementForExtension or IInputType method */ public IConfigurationElement getDependencyGeneratorElement(); + /** + * Returns the plugin.xml element of the dependencyGenerator extension or null if none. + * + * @param sourceExt source file extension + * @return IConfigurationElement + */ + public IConfigurationElement getDependencyGeneratorElementForExtension(String sourceExt); + /** * Sets the DependencyGenerator plugin.xml element * * @param element + * @deprecated - use IInputType method */ public void setDependencyGeneratorElement(IConfigurationElement element); @@ -317,9 +591,22 @@ public interface ITool extends IBuildObject { * when the project is built. * * @return IManagedDependencyGenerator + * @deprecated - use getDependencyGeneratorForExtension or IInputType method */ public IManagedDependencyGenerator getDependencyGenerator(); + /** + * Returns a class instance that implements an interface to generate + * source-level dependencies for the tool specified in the argument. + * This method may return null in which case, the receiver + * should assume that the tool does not require dependency information + * when the project is built. + * + * @param sourceExt source file extension + * @return IManagedDependencyGenerator + */ + public IManagedDependencyGenerator getDependencyGeneratorForExtension(String sourceExt); + /** * Returns an array of command line arguments that have been specified for * the tool. @@ -329,7 +616,7 @@ public interface ITool extends IBuildObject { public String[] getCommandFlags() throws BuildException; /** - * Answers the additional command line arguments the user has specified for + * Returns the command line arguments that have been specified for * the tool. * * @return String diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IToolChain.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IToolChain.java index 2cb1e89c228..b2b19ada5a7 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IToolChain.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/IToolChain.java @@ -12,7 +12,7 @@ package org.eclipse.cdt.managedbuilder.core; /** - * This class represents a tool-integrator-defined, ordered set of tools + * This interface represents a tool-integrator-defined, ordered set of tools * that transform the projects input into the projects outputs. A * tool-chain can be defined as part of a configuration, or as an * independent specification that is referenced in a separate configuration @@ -32,6 +32,8 @@ public interface IToolChain extends IBuildObject { public static final String OS_LIST = "osList"; //$NON-NLS-1$ public static final String ARCH_LIST = "archList"; //$NON-NLS-1$ public static final String ERROR_PARSERS = "errorParsers"; //$NON-NLS-1$ + public static final String TARGET_TOOL = "targetTool"; //$NON-NLS-1$ + public static final String SECONDARY_OUTPUTS = "secondaryOutputs"; //$NON-NLS-1$ public static final String IS_TOOL_CHAIN_SUPPORTED = "isToolChainSupported"; //$NON-NLS-1$ // The attribute name for the scanner info collector public static final String SCANNER_CONFIG_PROFILE_ID = "scannerConfigDiscoveryProfileId"; //$NON-NLS-1$ @@ -225,6 +227,38 @@ public interface IToolChain extends IBuildObject { */ public void setScannerConfigDiscoveryProfileId(String profileId); + /** + * Returns the id in this tool-chain that creates the build artifact. + * + * @return String + */ + public String getTargetToolId(); + + /** + * Sets the tool in this tool-chain that creates the build artifact. + * + * @param targetToolId + */ + public void setTargetTool(String targetToolId); + + /** + * Returns the OutputTypes in this tool-chain, besides the primary + * output of the targetTool, that are also considered to be build + * artifacts. + * + * @return IOutputType[] + */ + public IOutputType[] getSecondaryOutputs(); + + /** + * Sets the semicolon separated list of OutputType identifiers in + * this tool-chain, besides the primary output of the targetTool, + * that are also considered to be build artifacts. + * + * @param ids + */ + public void setSecondaryOutputs(String ids); + /** * Returns true if this tool-chain has changes that need to * be saved in the project file, else false. diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedBuildManager.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedBuildManager.java index c4d1c6876aa..fc5e97a4d69 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedBuildManager.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedBuildManager.java @@ -54,6 +54,8 @@ import org.eclipse.cdt.managedbuilder.internal.core.ManagedProject; import org.eclipse.cdt.managedbuilder.internal.core.Option; import org.eclipse.cdt.managedbuilder.internal.core.OptionCategory; import org.eclipse.cdt.managedbuilder.internal.core.ProjectType; +import org.eclipse.cdt.managedbuilder.internal.core.InputType; +import org.eclipse.cdt.managedbuilder.internal.core.OutputType; import org.eclipse.cdt.managedbuilder.internal.core.ResourceConfiguration; import org.eclipse.cdt.managedbuilder.internal.core.Target; import org.eclipse.cdt.managedbuilder.internal.core.TargetPlatform; @@ -132,6 +134,10 @@ public class ManagedBuildManager extends AbstractCExtension implements IScannerI private static Map extensionOptionMap; // Option Categories defined in the manifest files private static Map extensionOptionCategoryMap; + // Input types defined in the manifest files + private static Map extensionInputTypeMap; + // Output types defined in the manifest files + private static Map extensionOutputTypeMap; // Targets defined in the manifest files (CDT V2.0 object model) private static Map extensionTargetMap; // "Selected configuraton" elements defined in the manifest files. @@ -330,6 +336,30 @@ public class ManagedBuildManager extends AbstractCExtension implements IScannerI return extensionOptionCategoryMap; } + /* (non-Javadoc) + * Safe accessor for the map of IDs to InputTypes + * + * @return Map + */ + protected static Map getExtensionInputTypeMap() { + if (extensionInputTypeMap == null) { + extensionInputTypeMap = new HashMap(); + } + return extensionInputTypeMap; + } + + /* (non-Javadoc) + * Safe accessor for the map of IDs to OutputTypes + * + * @return Map + */ + protected static Map getExtensionOutputTypeMap() { + if (extensionOutputTypeMap == null) { + extensionOutputTypeMap = new HashMap(); + } + return extensionOutputTypeMap; + } + /* (non-Javadoc) * Safe accessor for the map of IDs to Targets (CDT V2.0 object model) * @@ -447,6 +477,28 @@ public class ManagedBuildManager extends AbstractCExtension implements IScannerI return (IOption) getExtensionOptionMap().get(id); } + /** + * Returns the InputType from the manifest with the ID specified in the argument + * or null. + * + * @param id + * @return IInputType + */ + public static IInputType getExtensionInputType(String id) { + return (IInputType) getExtensionInputTypeMap().get(id); + } + + /** + * Returns the OutputType from the manifest with the ID specified in the argument + * or null. + * + * @param id + * @return IOutputType + */ + public static IOutputType getExtensionOutputType(String id) { + return (IOutputType) getExtensionOutputTypeMap().get(id); + } + /** * Returns the target from the manifest with the ID specified in the argument * or null - CDT V2.0 object model. @@ -1048,6 +1100,40 @@ public class ManagedBuildManager extends AbstractCExtension implements IScannerI } } + /** + * Adds an InputType that is is specified in the manifest to the + * build system. It is available to any element that + * has a reference to it as part of its description. + * + * @param inputType + */ + public static void addExtensionInputType(InputType inputType) { + Object previous = getExtensionInputTypeMap().put(inputType.getId(), inputType); + if (previous != null) { + // Report error + ManagedBuildManager.OutputDuplicateIdError( + "InputType", //$NON-NLS-1$ + inputType.getId()); + } + } + + /** + * Adds an OutputType that is is specified in the manifest to the + * build system. It is available to any element that + * has a reference to it as part of its description. + * + * @param outputType + */ + public static void addExtensionOutputType(OutputType outputType) { + Object previous = getExtensionOutputTypeMap().put(outputType.getId(), outputType); + if (previous != null) { + // Report error + ManagedBuildManager.OutputDuplicateIdError( + "OutputType", //$NON-NLS-1$ + outputType.getId()); + } + } + /** * Adds a Target that is is specified in the manifest to the * build system. It is available to any CDT 2.0 object model element that diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/AdditionalInput.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/AdditionalInput.java new file mode 100644 index 00000000000..a33a4403667 --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/AdditionalInput.java @@ -0,0 +1,281 @@ +/********************************************************************** + * Copyright (c) 2005 Intel Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Intel Corporation - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.managedbuilder.internal.core; + +import org.eclipse.cdt.managedbuilder.core.IInputType; +import org.eclipse.cdt.managedbuilder.core.IAdditionalInput; +import org.eclipse.cdt.managedbuilder.core.IManagedConfigElement; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +public class AdditionalInput implements IAdditionalInput { + + private static final String EMPTY_STRING = new String(); + + // Superclass + // Parent and children + private IInputType parent; + // Managed Build model attributes + private String paths; + private Integer kind; + // Miscellaneous + private boolean isExtensionAdditionalInput = false; + private boolean isDirty = false; + private boolean resolved = true; + + /* + * C O N S T R U C T O R S + */ + + /** + * This constructor is called to create an AdditionalInput defined by an extension point in + * a plugin manifest file, or returned by a dynamic element provider + * + * @param parent The IInputType parent of this AdditionalInput + * @param element The AdditionalInput definition from the manifest file or a dynamic element + * provider + */ + public AdditionalInput(IInputType parent, IManagedConfigElement element) { + this.parent = parent; + isExtensionAdditionalInput = true; + + // setup for resolving + resolved = false; + + loadFromManifest(element); + } + + /** + * This constructor is called to create an AdditionalInput whose attributes and children will be + * added by separate calls. + * + * @param InputType The parent of the an AdditionalInput + * @param boolean Indicates whether this is an extension element or a managed project element + */ + public AdditionalInput(InputType parent, boolean isExtensionElement) { + this.parent = parent; + isExtensionAdditionalInput = isExtensionElement; + if (!isExtensionElement) { + setDirty(true); + } + } + + /** + * Create an AdditionalInput based on the specification stored in the + * project file (.cdtbuild). + * + * @param parent The ITool the AdditionalInput will be added to. + * @param element The XML element that contains the AdditionalInput settings. + */ + public AdditionalInput(IInputType parent, Element element) { + this.parent = parent; + isExtensionAdditionalInput = false; + + // Initialize from the XML attributes + loadFromProject(element); + } + + /** + * Create an AdditionalInput based upon an existing AdditionalInput. + * + * @param parent The IInputType the AdditionalInput will be added to. + * @param additionalInput The existing AdditionalInput to clone. + */ + public AdditionalInput(IInputType parent, AdditionalInput additionalInput) { + this.parent = parent; + isExtensionAdditionalInput = false; + + // Copy the remaining attributes + if (additionalInput.paths != null) { + paths = new String(additionalInput.paths); + } + + if (additionalInput.kind != null) { + kind = new Integer(additionalInput.kind.intValue()); + } + + setDirty(true); + } + + /* + * E L E M E N T A T T R I B U T E R E A D E R S A N D W R I T E R S + */ + + /* (non-Javadoc) + * Loads the AdditionalInput information from the ManagedConfigElement specified in the + * argument. + * + * @param element Contains the AdditionalInput information + */ + protected void loadFromManifest(IManagedConfigElement element) { + + // path + paths = element.getAttribute(IAdditionalInput.PATHS); + + // kind + String kindStr = element.getAttribute(IAdditionalInput.KIND); + if (kindStr == null || kindStr.equals(ADDITIONAL_INPUT_DEPENDENCY)) { + kind = new Integer(KIND_ADDITIONAL_INPUT_DEPENDENCY); + } else if (kindStr.equals(ADDITIONAL_INPUT)) { + kind = new Integer(KIND_ADDITIONAL_INPUT); + } else if (kindStr.equals(ADDITIONAL_DEPENDENCY)) { + kind = new Integer(KIND_ADDITIONAL_DEPENDENCY); + } + } + + /* (non-Javadoc) + * Initialize the AdditionalInput information from the XML element + * specified in the argument + * + * @param element An XML element containing the AdditionalInput information + */ + protected void loadFromProject(Element element) { + + // path + if (element.hasAttribute(IAdditionalInput.PATHS)) { + paths = element.getAttribute(IAdditionalInput.PATHS); + } + + // kind + if (element.hasAttribute(IAdditionalInput.KIND)) { + String kindStr = element.getAttribute(IAdditionalInput.KIND); + if (kindStr == null || kindStr.equals(ADDITIONAL_INPUT_DEPENDENCY)) { + kind = new Integer(KIND_ADDITIONAL_INPUT_DEPENDENCY); + } else if (kindStr.equals(ADDITIONAL_INPUT)) { + kind = new Integer(KIND_ADDITIONAL_INPUT); + } else if (kindStr.equals(ADDITIONAL_DEPENDENCY)) { + kind = new Integer(KIND_ADDITIONAL_DEPENDENCY); + } + } + } + + /** + * Persist the AdditionalInput to the project file. + * + * @param doc + * @param element + */ + public void serialize(Document doc, Element element) { + + if (paths != null) { + element.setAttribute(IAdditionalInput.PATHS, paths); + } + + if (kind != null) { + String str; + switch (getKind()) { + case KIND_ADDITIONAL_INPUT: + str = ADDITIONAL_INPUT; + break; + case KIND_ADDITIONAL_DEPENDENCY: + str = ADDITIONAL_DEPENDENCY; + break; + case KIND_ADDITIONAL_INPUT_DEPENDENCY: + str = ADDITIONAL_INPUT_DEPENDENCY; + break; + default: + str = EMPTY_STRING; + break; + } + element.setAttribute(IAdditionalInput.KIND, str); + } + + // I am clean now + isDirty = false; + } + + /* + * P A R E N T A N D C H I L D H A N D L I N G + */ + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IAdditionalInput#getParent() + */ + public IInputType getParent() { + return parent; + } + + /* + * M O D E L A T T R I B U T E A C C E S S O R S + */ + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IAdditionalInput#getPaths() + */ + public String getPaths() { + return paths; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IAdditionalInput#setPaths() + */ + public void setPaths(String newPaths) { + if (paths == null && newPaths == null) return; + if (paths == null || newPaths == null || !(paths.equals(newPaths))) { + paths = newPaths; + isDirty = true; + } + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IAdditionalInput#getKind() + */ + public int getKind() { + return kind.intValue(); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IAdditionalInput#setKind() + */ + public void setKind(int newKind) { + if (kind == null || !(kind.intValue() == newKind)) { + kind = new Integer(newKind); + isDirty = true; + } + } + + /* + * O B J E C T S T A T E M A I N T E N A N C E + */ + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.core.IAdditionalInput#isExtensionElement() + */ + public boolean isExtensionElement() { + return isExtensionAdditionalInput; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.core.IAdditionalInput#isDirty() + */ + public boolean isDirty() { + // This shouldn't be called for an extension AdditionalInput + if (isExtensionAdditionalInput) return false; + return isDirty; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.core.IAdditionalInput#setDirty(boolean) + */ + public void setDirty(boolean isDirty) { + this.isDirty = isDirty; + } + + /* (non-Javadoc) + * Resolve the element IDs to interface references + */ + public void resolveReferences() { + if (!resolved) { + resolved = true; + } + } + +} diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Builder.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Builder.java index 014f41b2cc4..43f3f600907 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Builder.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Builder.java @@ -1,5 +1,5 @@ /********************************************************************** - * Copyright (c) 2004 Intel Corporation and others. + * Copyright (c) 2004, 2005 Intel Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at @@ -77,8 +77,8 @@ public class Builder extends BuildObject implements IBuilder { * * @param ToolChain The parent of the builder, if any * @param Builder The superClass, if any - * @param String The id for the new tool chain - * @param String The name for the new tool chain + * @param String The id for the new Builder + * @param String The name for the new Builder * @param boolean Indicates whether this is an extension element or a managed project element */ public Builder(ToolChain parent, IBuilder superClass, String Id, String name, boolean isExtensionElement) { @@ -157,10 +157,10 @@ public class Builder extends BuildObject implements IBuilder { */ /* (non-Javadoc) - * Loads the project-type information from the ManagedConfigElement specified in the + * Loads the builder information from the ManagedConfigElement specified in the * argument. * - * @param element Contains the tool-chain information + * @param element Contains the Builder information */ protected void loadFromManifest(IManagedConfigElement element) { ManagedBuildManager.putConfigElement(this, element); diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Configuration.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Configuration.java index 106bf84b4f1..bb86377bbcc 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Configuration.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Configuration.java @@ -596,6 +596,29 @@ public class Configuration extends BuildObject implements IConfiguration { return toolChain.getTool(id); } + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.core.IConfiguration#getTargetTool() + */ + public ITool getTargetTool() { + String targetToolId = toolChain.getTargetToolId(); + if (targetToolId == null) return null; + + // Look for a tool with this ID, or a tool with a superclass with this id + ITool[] tools = getFilteredTools(); + for (int i = 0; i < tools.length; i++) { + ITool targetTool = tools[i]; + ITool tool = targetTool; + do { + if (targetToolId.equals(tool.getId())) { + return targetTool; + } + tool = tool.getSuperClass(); + } while (tool != null); + } + + return null; + } + /* (non-Javadoc) * @see org.eclipse.cdt.managedbuilder.core.IConfiguration#setToolCommand(org.eclipse.cdt.managedbuilder.core.ITool, java.lang.String) */ diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/GeneratedMakefileBuilder.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/GeneratedMakefileBuilder.java index 9bc11868d84..1198912dd7a 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/GeneratedMakefileBuilder.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/GeneratedMakefileBuilder.java @@ -174,8 +174,6 @@ public class GeneratedMakefileBuilder extends ACBuilder { protected Vector generationProblems; protected IProject[] referencedProjects; protected List resourcesToBuild; - protected List ruleList; - public static void outputTrace(String resourceName, String message) { if (VERBOSE) { System.out.println(TRACE_HEADER + resourceName + TRACE_FOOTER + message + NEWLINE); @@ -373,7 +371,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { checkCancel(monitor); String statusMsg = ManagedMakeMessages.getFormattedString("ManagedMakeBuilder.message.rebuild.makefiles", getProject().getName()); //$NON-NLS-1$ monitor.subTask(statusMsg); - generator = ManagedBuildManager.getBuildfileGenerator(info.getDefaultConfiguration()); + //generator = ManagedBuildManager.getBuildfileGenerator(info.getDefaultConfiguration()); generator.initialize(getProject(), info, monitor); MultiStatus result = generator.regenerateMakefiles(); if (result.getCode() == IStatus.WARNING || result.getCode() == IStatus.INFO) { @@ -415,7 +413,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { throw e; } - // Say bye bye + // Build finished message statusMsg = ManagedMakeMessages.getFormattedString(BUILD_FINISHED, getProject().getName()); //$NON-NLS-1$ monitor.subTask(statusMsg); } @@ -463,19 +461,6 @@ public class GeneratedMakefileBuilder extends ACBuilder { return resourcesToBuild; } - /* (non-javadoc) - * Answers the list of build rules that have been assembled. If there are none, - * answers an empty list, never null - * - * @return - */ - protected List getRuleList() { - if (ruleList == null) { - ruleList = new ArrayList(); - } - return ruleList; - } - /* (non-Javadoc) * @see org.eclipse.cdt.core.resources.ACBuilder#getWorkingDirectory() */ @@ -538,7 +523,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { throw e; } - // Say bye bye + // Build finished message statusMsg = ManagedMakeMessages.getFormattedString(BUILD_FINISHED, getProject().getName()); //$NON-NLS-1$ monitor.subTask(statusMsg); } diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/InputOrder.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/InputOrder.java new file mode 100644 index 00000000000..fcb89448035 --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/InputOrder.java @@ -0,0 +1,294 @@ +/********************************************************************** + * Copyright (c) 2005 Intel Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Intel Corporation - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.managedbuilder.internal.core; + +import org.eclipse.cdt.managedbuilder.core.IInputType; +import org.eclipse.cdt.managedbuilder.core.IInputOrder; +import org.eclipse.cdt.managedbuilder.core.IManagedConfigElement; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +public class InputOrder implements IInputOrder { + + private static final String EMPTY_STRING = new String(); + + // Superclass + // Parent and children + private IInputType parent; + // Managed Build model attributes + private String path; + private String order; + private Boolean excluded; + // Miscellaneous + private boolean isExtensionInputOrder = false; + private boolean isDirty = false; + private boolean resolved = true; + + /* + * C O N S T R U C T O R S + */ + + /** + * This constructor is called to create an InputOrder defined by an extension point in + * a plugin manifest file, or returned by a dynamic element provider + * + * @param parent The IInputType parent of this InputOrder + * @param element The InputOrder definition from the manifest file or a dynamic element + * provider + */ + public InputOrder(IInputType parent, IManagedConfigElement element) { + this.parent = parent; + isExtensionInputOrder = true; + + // setup for resolving + resolved = false; + + loadFromManifest(element); + } + + /** + * This constructor is called to create an InputOrder whose attributes and children will be + * added by separate calls. + * + * @param InputType The parent of the an InputOrder + * @param boolean Indicates whether this is an extension element or a managed project element + */ + public InputOrder(InputType parent, boolean isExtensionElement) { + this.parent = parent; + isExtensionInputOrder = isExtensionElement; + if (!isExtensionElement) { + setDirty(true); + } + } + + /** + * Create an InputOrder based on the specification stored in the + * project file (.cdtbuild). + * + * @param parent The ITool the InputOrder will be added to. + * @param element The XML element that contains the InputOrder settings. + */ + public InputOrder(IInputType parent, Element element) { + this.parent = parent; + isExtensionInputOrder = false; + + // Initialize from the XML attributes + loadFromProject(element); + } + + /** + * Create an InputOrder based upon an existing InputOrder. + * + * @param parent The IInputType the InputOrder will be added to. + * @param inputOrder The existing InputOrder to clone. + */ + public InputOrder(IInputType parent, InputOrder inputOrder) { + this.parent = parent; + isExtensionInputOrder = false; + + // Copy the remaining attributes + if (inputOrder.path != null) { + path = new String(inputOrder.path); + } + + if (inputOrder.order != null) { + order = new String(inputOrder.order); + } + + if (inputOrder.excluded != null) { + excluded = new Boolean(inputOrder.excluded.booleanValue()); + } + + setDirty(true); + } + + /* + * E L E M E N T A T T R I B U T E R E A D E R S A N D W R I T E R S + */ + + /* (non-Javadoc) + * Loads the InputOrder information from the ManagedConfigElement specified in the + * argument. + * + * @param element Contains the InputOrder information + */ + protected void loadFromManifest(IManagedConfigElement element) { + + // path + path = element.getAttribute(IInputOrder.PATH); + + // order + order = element.getAttribute(IInputOrder.ORDER); + + // excluded + String isEx = element.getAttribute(IInputOrder.EXCLUDED); + if (isEx != null){ + excluded = new Boolean("true".equals(isEx)); //$NON-NLS-1$ + } + } + + /* (non-Javadoc) + * Initialize the InputOrder information from the XML element + * specified in the argument + * + * @param element An XML element containing the InputOrder information + */ + protected void loadFromProject(Element element) { + + // path + if (element.hasAttribute(IInputOrder.PATH)) { + path = element.getAttribute(IInputOrder.PATH); + } + + // order + if (element.hasAttribute(IInputOrder.ORDER)) { + order = element.getAttribute(IInputOrder.ORDER); + } + + // excluded + if (element.hasAttribute(IInputOrder.EXCLUDED)) { + String isEx = element.getAttribute(IInputOrder.EXCLUDED); + if (isEx != null){ + excluded = new Boolean("true".equals(isEx)); //$NON-NLS-1$ + } + } + } + + /** + * Persist the InputOrder to the project file. + * + * @param doc + * @param element + */ + public void serialize(Document doc, Element element) { + + if (path != null) { + element.setAttribute(IInputOrder.PATH, path); + } + + if (order != null) { + element.setAttribute(IInputOrder.ORDER, order); + } + + if (excluded != null) { + element.setAttribute(IInputOrder.EXCLUDED, excluded.toString()); + } + + // I am clean now + isDirty = false; + } + + /* + * P A R E N T A N D C H I L D H A N D L I N G + */ + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputOrder#getParent() + */ + public IInputType getParent() { + return parent; + } + + /* + * M O D E L A T T R I B U T E A C C E S S O R S + */ + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputOrder#getPsth() + */ + public String getPath() { + return path; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputOrder#setPath() + */ + public void setPath(String newPath) { + if (path == null && newPath == null) return; + if (path == null || newPath == null || !(path.equals(newPath))) { + path = newPath; + isDirty = true; + } + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputOrder#getOrder() + */ + public String getOrder() { + return order; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputOrder#setOrder() + */ + public void setOrder(String newOrder) { + if (order == null && newOrder == null) return; + if (order == null || newOrder == null || !(order.equals(newOrder))) { + order = newOrder; + isDirty = true; + } + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputOrder#getExcluded() + */ + public boolean getExcluded() { + return excluded.booleanValue(); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputOrder#setExcluded() + */ + public void setExcluded(boolean b) { + if (excluded == null || !(b == excluded.booleanValue())) { + excluded = new Boolean(b); + setDirty(true); + } + } + + + /* + * O B J E C T S T A T E M A I N T E N A N C E + */ + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.core.IInputOrder#isExtensionElement() + */ + public boolean isExtensionElement() { + return isExtensionInputOrder; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.core.IInputOrder#isDirty() + */ + public boolean isDirty() { + // This shouldn't be called for an extension InputOrder + if (isExtensionInputOrder) return false; + return isDirty; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.core.IInputOrder#setDirty(boolean) + */ + public void setDirty(boolean isDirty) { + this.isDirty = isDirty; + } + + /* (non-Javadoc) + * Resolve the element IDs to interface references + */ + public void resolveReferences() { + if (!resolved) { + resolved = true; + } + } + +} diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/InputType.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/InputType.java new file mode 100644 index 00000000000..015f080e8dd --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/InputType.java @@ -0,0 +1,1111 @@ +/********************************************************************** + * Copyright (c) 2005 Intel Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Intel Corporation - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.managedbuilder.internal.core; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.StringTokenizer; +import java.util.Vector; + +import org.eclipse.core.runtime.content.*; +import org.eclipse.cdt.managedbuilder.core.IBuildObject; +import org.eclipse.cdt.managedbuilder.core.IProjectType; +import org.eclipse.cdt.managedbuilder.core.ITool; +import org.eclipse.cdt.managedbuilder.core.IInputType; +import org.eclipse.cdt.managedbuilder.core.IInputOrder; +import org.eclipse.cdt.managedbuilder.core.IAdditionalInput; +import org.eclipse.cdt.managedbuilder.core.IManagedConfigElement; +import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; +import org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyGenerator; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class InputType extends BuildObject implements IInputType { + + private static final String DEFAULT_SEPARATOR = ","; //$NON-NLS-1$ + private static final String EMPTY_STRING = new String(); + + // Superclass + private IInputType superClass; + private String superClassId; + // Parent and children + private ITool parent; + private Vector inputOrderList; + private Vector additionalInputList; + // Managed Build model attributes + private String sourceContentTypeId; + private IContentType sourceContentType; + private List inputExtensions; + private String dependencyContentTypeId; + private IContentType dependencyContentType; + private List dependencyExtensions; + private String optionId; + private String buildVariable; + private Boolean multipleOfType; + private Boolean primaryInput; + private IConfigurationElement dependencyGeneratorElement = null; + private IManagedDependencyGenerator dependencyGenerator = null; + // Miscellaneous + private boolean isExtensionInputType = false; + private boolean isDirty = false; + private boolean resolved = true; + + /* + * C O N S T R U C T O R S + */ + + /** + * This constructor is called to create an InputType defined by an extension point in + * a plugin manifest file, or returned by a dynamic element provider + * + * @param parent The ITool parent of this InputType + * @param element The InputType definition from the manifest file or a dynamic element + * provider + */ + public InputType(ITool parent, IManagedConfigElement element) { + this.parent = parent; + isExtensionInputType = true; + + // setup for resolving + resolved = false; + + loadFromManifest(element); + + // Hook me up to the Managed Build Manager + ManagedBuildManager.addExtensionInputType(this); + + // Load Children + IManagedConfigElement[] iElements = element.getChildren(); + for (int l = 0; l < iElements.length; ++l) { + IManagedConfigElement iElement = iElements[l]; + if (iElement.getName().equals(IInputOrder.INPUT_ORDER_ELEMENT_NAME)) { + InputOrder inputOrder = new InputOrder(this, iElement); + getInputOrderList().add(inputOrder); + } else if (iElement.getName().equals(IAdditionalInput.ADDITIONAL_INPUT_ELEMENT_NAME)) { + AdditionalInput addlInput = new AdditionalInput(this, iElement); + getAdditionalInputList().add(addlInput); + } + } + } + + /** + * This constructor is called to create an InputType whose attributes and children will be + * added by separate calls. + * + * @param Tool The parent of the an InputType + * @param InputType The superClass, if any + * @param String The id for the new InputType + * @param String The name for the new InputType + * @param boolean Indicates whether this is an extension element or a managed project element + */ + public InputType(Tool parent, IInputType superClass, String Id, String name, boolean isExtensionElement) { + this.parent = parent; + this.superClass = superClass; + if (this.superClass != null) { + superClassId = this.superClass.getId(); + } + setId(Id); + setName(name); + isExtensionInputType = isExtensionElement; + if (isExtensionElement) { + // Hook me up to the Managed Build Manager + ManagedBuildManager.addExtensionInputType(this); + } else { + setDirty(true); + } + } + + /** + * Create an InputType based on the specification stored in the + * project file (.cdtbuild). + * + * @param parent The ITool the InputType will be added to. + * @param element The XML element that contains the InputType settings. + */ + public InputType(ITool parent, Element element) { + this.parent = parent; + isExtensionInputType = false; + + // Initialize from the XML attributes + loadFromProject(element); + + // Load children + NodeList configElements = element.getChildNodes(); + for (int i = 0; i < configElements.getLength(); ++i) { + Node configElement = configElements.item(i); + if (configElement.getNodeName().equals(IInputOrder.INPUT_ORDER_ELEMENT_NAME)) { + InputOrder inputOrder = new InputOrder(this, (Element)configElement); + getInputOrderList().add(inputOrder); + } else if (configElement.getNodeName().equals(IAdditionalInput.ADDITIONAL_INPUT_ELEMENT_NAME)) { + AdditionalInput addlInput = new AdditionalInput(this, (Element)configElement); + getAdditionalInputList().add(addlInput); + } + } + } + + /** + * Create an InputType based upon an existing InputType. + * + * @param parent The ITool the InputType will be added to. + * @param Id The identifier of the new InputType + * @param name The name of the new InputType + * @param inputType The existing InputType to clone. + */ + public InputType(ITool parent, String Id, String name, InputType inputType) { + this.parent = parent; + superClass = inputType.superClass; + if (superClass != null) { + if (inputType.superClassId != null) { + superClassId = new String(inputType.superClassId); + } + } + setId(Id); + setName(name); + isExtensionInputType = false; + + // Copy the remaining attributes + + if (inputType.sourceContentTypeId != null) { + sourceContentTypeId = new String(inputType.sourceContentTypeId); + } + sourceContentType = inputType.sourceContentType; + if (inputType.inputExtensions != null) { + inputExtensions = new ArrayList(inputType.inputExtensions); + } + if (inputType.dependencyContentTypeId != null) { + dependencyContentTypeId = new String(inputType.dependencyContentTypeId); + } + dependencyContentType = inputType.dependencyContentType; + if (inputType.dependencyExtensions != null) { + dependencyExtensions = new ArrayList(inputType.dependencyExtensions); + } + if (inputType.optionId != null) { + optionId = new String(inputType.optionId); + } + if (inputType.buildVariable != null) { + buildVariable = new String(inputType.buildVariable); + } + if (inputType.multipleOfType != null) { + multipleOfType = new Boolean(inputType.multipleOfType.booleanValue()); + } + if (inputType.primaryInput != null) { + primaryInput = new Boolean(inputType.primaryInput.booleanValue()); + } + dependencyGeneratorElement = inputType.dependencyGeneratorElement; + dependencyGenerator = inputType.dependencyGenerator; + + // Clone the children + if (inputType.inputOrderList != null) { + Iterator iter = inputType.getInputOrderList().listIterator(); + while (iter.hasNext()) { + InputOrder inputOrder = (InputOrder) iter.next(); + InputOrder newInputOrder = new InputOrder(this, inputOrder); + getInputOrderList().add(newInputOrder); + } + } + if (inputType.additionalInputList != null) { + Iterator iter = inputType.getAdditionalInputList().listIterator(); + while (iter.hasNext()) { + AdditionalInput additionalInput = (AdditionalInput) iter.next(); + AdditionalInput newAdditionalInput = new AdditionalInput(this, additionalInput); + getAdditionalInputList().add(newAdditionalInput); + } + } + + setDirty(true); + } + + /* + * E L E M E N T A T T R I B U T E R E A D E R S A N D W R I T E R S + */ + + /* (non-Javadoc) + * Loads the InputType information from the ManagedConfigElement specified in the + * argument. + * + * @param element Contains the InputType information + */ + protected void loadFromManifest(IManagedConfigElement element) { + ManagedBuildManager.putConfigElement(this, element); + + // id + setId(element.getAttribute(IBuildObject.ID)); + + // Get the name + setName(element.getAttribute(IBuildObject.NAME)); + + // superClass + superClassId = element.getAttribute(IProjectType.SUPERCLASS); + + // sourceContentType + sourceContentTypeId = element.getAttribute(IInputType.SOURCE_CONTENT_TYPE); + + // Get the supported input file extensions + String inputs = element.getAttribute(ITool.SOURCES); + if (inputs != null) { + StringTokenizer tokenizer = new StringTokenizer(inputs, DEFAULT_SEPARATOR); + while (tokenizer.hasMoreElements()) { + getInputExtensionsList().add(tokenizer.nextElement()); + } + } + + // dependencyContentType + dependencyContentTypeId = element.getAttribute(IInputType.DEPENDENCY_CONTENT_TYPE); + + // Get the dependency (header file) extensions + String headers = element.getAttribute(IInputType.DEPENDENCY_EXTENSIONS); + if (headers != null) { + StringTokenizer tokenizer = new StringTokenizer(headers, DEFAULT_SEPARATOR); + while (tokenizer.hasMoreElements()) { + getDependencyExtensionsList().add(tokenizer.nextElement()); + } + } + + // option + optionId = element.getAttribute(IInputType.OPTION); + + // multipleOfType + String isMOT = element.getAttribute(IInputType.MULTIPLE_OF_TYPE); + if (isMOT != null){ + multipleOfType = new Boolean("true".equals(isMOT)); //$NON-NLS-1$ + } + + // primaryInput + String isPI = element.getAttribute(IInputType.PRIMARY_INPUT); + if (isPI != null){ + primaryInput = new Boolean("true".equals(isPI)); //$NON-NLS-1$ + } + + // buildVariable + buildVariable = element.getAttribute(IInputType.BUILD_VARIABLE); + + // Store the configuration element IFF there is a dependency generator defined + String depGenerator = element.getAttribute(ITool.DEP_CALC_ID); + if (depGenerator != null && element instanceof DefaultManagedConfigElement) { + dependencyGeneratorElement = ((DefaultManagedConfigElement)element).getConfigurationElement(); + } + } + + /* (non-Javadoc) + * Initialize the InputType information from the XML element + * specified in the argument + * + * @param element An XML element containing the InputType information + */ + protected boolean loadFromProject(Element element) { + + // id + setId(element.getAttribute(IBuildObject.ID)); + + // name + if (element.hasAttribute(IBuildObject.NAME)) { + setName(element.getAttribute(IBuildObject.NAME)); + } + + // superClass + superClassId = element.getAttribute(IProjectType.SUPERCLASS); + if (superClassId != null && superClassId.length() > 0) { + superClass = ManagedBuildManager.getExtensionInputType(superClassId); + if (superClass == null) { + // TODO: Report error + } + } + + // sourceContentType + IContentTypeManager manager = Platform.getContentTypeManager(); + if (element.hasAttribute(IInputType.SOURCE_CONTENT_TYPE)) { + sourceContentTypeId = element.getAttribute(IInputType.SOURCE_CONTENT_TYPE); + if (sourceContentTypeId != null && sourceContentTypeId.length() > 0) { + sourceContentType = manager.getContentType(sourceContentTypeId); + } + } + + // sources + if (element.hasAttribute(IInputType.SOURCES)) { + String inputs = element.getAttribute(ITool.SOURCES); + if (inputs != null) { + StringTokenizer tokenizer = new StringTokenizer(inputs, DEFAULT_SEPARATOR); + while (tokenizer.hasMoreElements()) { + getInputExtensionsList().add(tokenizer.nextElement()); + } + } + } + + // dependencyContentType + if (element.hasAttribute(IInputType.DEPENDENCY_CONTENT_TYPE)) { + dependencyContentTypeId = element.getAttribute(IInputType.DEPENDENCY_CONTENT_TYPE); + if (dependencyContentTypeId != null && dependencyContentTypeId.length() > 0) { + dependencyContentType = manager.getContentType(dependencyContentTypeId); + } + } + + // dependencyExtensions + // Get the dependency (header file) extensions + if (element.hasAttribute(IInputType.DEPENDENCY_EXTENSIONS)) { + String headers = element.getAttribute(IInputType.DEPENDENCY_EXTENSIONS); + if (headers != null) { + StringTokenizer tokenizer = new StringTokenizer(headers, DEFAULT_SEPARATOR); + while (tokenizer.hasMoreElements()) { + getDependencyExtensionsList().add(tokenizer.nextElement()); + } + } + } + + // option + if (element.hasAttribute(IInputType.OPTION)) { + optionId = element.getAttribute(IInputType.OPTION); + } + + // multipleOfType + if (element.hasAttribute(IInputType.MULTIPLE_OF_TYPE)) { + String isMOT = element.getAttribute(IInputType.MULTIPLE_OF_TYPE); + if (isMOT != null){ + multipleOfType = new Boolean("true".equals(isMOT)); //$NON-NLS-1$ + } + } + + // primaryInput + if (element.hasAttribute(IInputType.PRIMARY_INPUT)) { + String isPI = element.getAttribute(IInputType.PRIMARY_INPUT); + if (isPI != null){ + primaryInput = new Boolean("true".equals(isPI)); //$NON-NLS-1$ + } + } + + // buildVariable + if (element.hasAttribute(IInputType.BUILD_VARIABLE)) { + buildVariable = element.getAttribute(IInputType.BUILD_VARIABLE); + } + + // Note: dependency generator cannot be specified in a project file because + // an IConfigurationElement is needed to load it! + if (element.hasAttribute(ITool.DEP_CALC_ID)) { + // TODO: Issue warning? + } + + return true; + } + + /** + * Persist the InputType to the project file. + * + * @param doc + * @param element + */ + public void serialize(Document doc, Element element) { + if (superClass != null) + element.setAttribute(IProjectType.SUPERCLASS, superClass.getId()); + + element.setAttribute(IBuildObject.ID, id); + + if (name != null) { + element.setAttribute(IBuildObject.NAME, name); + } + + // sourceContentType + if (sourceContentTypeId != null) { + element.setAttribute(IInputType.SOURCE_CONTENT_TYPE, sourceContentTypeId); + } + + // input file extensions + if (getInputExtensionsList().size() > 0) { + String inputs; + List list = getInputExtensionsList(); + Iterator iter = list.listIterator(); + inputs = (String)iter.next(); + while (iter.hasNext()) { + inputs += DEFAULT_SEPARATOR; + inputs += iter.next(); + } + element.setAttribute(IInputType.SOURCES, inputs); + } + + // dependencyContentType + if (dependencyContentTypeId != null) { + element.setAttribute(IInputType.DEPENDENCY_CONTENT_TYPE, dependencyContentTypeId); + } + + // dependency (header file) extensions + if (getDependencyExtensionsList().size() > 0) { + String headers; + List list = getDependencyExtensionsList(); + Iterator iter = list.listIterator(); + headers = (String)iter.next(); + while (iter.hasNext()) { + headers += DEFAULT_SEPARATOR; + headers += iter.next(); + } + element.setAttribute(IInputType.DEPENDENCY_EXTENSIONS, headers); + } + + if (optionId != null) { + element.setAttribute(IInputType.OPTION, optionId); + } + + if (multipleOfType != null) { + element.setAttribute(IInputType.MULTIPLE_OF_TYPE, multipleOfType.toString()); + } + + if (primaryInput != null) { + element.setAttribute(IInputType.PRIMARY_INPUT, primaryInput.toString()); + } + + if (buildVariable != null) { + element.setAttribute(IInputType.BUILD_VARIABLE, buildVariable); + } + + // Note: dependency generator cannot be specified in a project file because + // an IConfigurationElement is needed to load it! + if (dependencyGeneratorElement != null) { + // TODO: issue warning? + } + + // Serialize my children + List childElements = getInputOrderList(); + Iterator iter = childElements.listIterator(); + while (iter.hasNext()) { + InputOrder io = (InputOrder) iter.next(); + Element ioElement = doc.createElement(InputOrder.INPUT_ORDER_ELEMENT_NAME); + element.appendChild(ioElement); + io.serialize(doc, ioElement); + } + childElements = getAdditionalInputList(); + iter = childElements.listIterator(); + while (iter.hasNext()) { + AdditionalInput ai = (AdditionalInput) iter.next(); + Element aiElement = doc.createElement(AdditionalInput.ADDITIONAL_INPUT_ELEMENT_NAME); + element.appendChild(aiElement); + ai.serialize(doc, aiElement); + } + + // I am clean now + isDirty = false; + } + + /* + * P A R E N T A N D C H I L D H A N D L I N G + */ + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputType#getParent() + */ + public ITool getParent() { + return parent; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputType#createInputOrder() + */ + public IInputOrder createInputOrder(String path) { + InputOrder inputOrder = new InputOrder(this, false); + inputOrder.setPath(path); + getInputOrderList().add(inputOrder); + setDirty(true); + return inputOrder; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputType#getInputOrders() + */ + public IInputOrder[] getInputOrders() { + IInputOrder[] orders; + Vector ours = getInputOrderList(); + orders = (IInputOrder[])ours.toArray(new IInputOrder[ours.size()]); + return orders; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputType#getInputOrder() + */ + public IInputOrder getInputOrder(String path) { + // TODO Convert both paths to absolute? + List orders = getInputOrderList(); + Iterator iter = orders.listIterator(); + while (iter.hasNext()) { + InputOrder io = (InputOrder) iter.next(); + if (path.compareToIgnoreCase(io.getPath()) != 0) { + return io; + } + } + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputType#removeInputOrder() + */ + public void removeInputOrder(String path) { + IInputOrder order = getInputOrder(path); + if (order != null) removeInputOrder(order); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputType#removeInputOrder() + */ + public void removeInputOrder(IInputOrder element) { + getInputOrderList().remove(element); + setDirty(true); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputType#createAdditionalInput() + */ + public IAdditionalInput createAdditionalInput(String paths) { + AdditionalInput addlInput = new AdditionalInput(this, false); + addlInput.setPaths(paths); + getAdditionalInputList().add(addlInput); + setDirty(true); + return addlInput; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputType#getAdditionalInputs() + */ + public IAdditionalInput[] getAdditionalInputs() { + IAdditionalInput[] inputs; + Vector ours = getAdditionalInputList(); + inputs = (IAdditionalInput[])ours.toArray(new IAdditionalInput[ours.size()]); + return inputs; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputType#getAdditionalInput() + */ + public IAdditionalInput getAdditionalInput(String paths) { + // TODO Convert both paths to absolute? + // Must match all strings + String[] inputTokens = paths.split(";"); //$NON-NLS-1$ + List inputs = getInputOrderList(); + Iterator iter = inputs.listIterator(); + while (iter.hasNext()) { + AdditionalInput ai = (AdditionalInput) iter.next(); + boolean match = false; + String[] tokens = ai.getPaths().split(";"); //$NON-NLS-1$ + if (tokens.length == inputTokens.length) { + match = true; + for (int i = 0; i < tokens.length; i++) { + if (tokens[i].compareToIgnoreCase(inputTokens[i]) != 0) { + match = false; + break; + } + } + } + if (match) return ai; + } + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputType#removeAdditionalInput() + */ + public void removeAdditionalInput(String path) { + IAdditionalInput input = getAdditionalInput(path); + if (input != null) removeAdditionalInput(input); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputType#removeAdditionalInput() + */ + public void removeAdditionalInput(IAdditionalInput element) { + getAdditionalInputList().remove(element); + setDirty(true); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputType#getAdditionalDependencies() + */ + public IPath[] getAdditionalDependencies() { + List deps = new ArrayList(); + Iterator typeIter = getAdditionalInputList().iterator(); + while (typeIter.hasNext()) { + AdditionalInput current = (AdditionalInput)typeIter.next(); + int kind = current.getKind(); + if (kind == IAdditionalInput.KIND_ADDITIONAL_DEPENDENCY || + kind == IAdditionalInput.KIND_ADDITIONAL_INPUT_DEPENDENCY) { + String paths = current.getPaths(); + if (paths != null) { + String[] pathTokens = paths.split(";"); //$NON-NLS-1$ + for (int i = 0; i < pathTokens.length; i++) { + deps.add(Path.fromOSString(pathTokens[i])); + } + } + } + } + return (IPath[])deps.toArray(new IPath[deps.size()]); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputType#getAdditionalResources() + */ + public IPath[] getAdditionalResources() { + List ins = new ArrayList(); + Iterator typeIter = getAdditionalInputList().iterator(); + while (typeIter.hasNext()) { + AdditionalInput current = (AdditionalInput)typeIter.next(); + int kind = current.getKind(); + if (kind == IAdditionalInput.KIND_ADDITIONAL_INPUT || + kind == IAdditionalInput.KIND_ADDITIONAL_INPUT_DEPENDENCY) { + String paths = current.getPaths(); + if (paths != null) { + String[] pathTokens = paths.split(";"); //$NON-NLS-1$ + for (int i = 0; i < pathTokens.length; i++) { + ins.add(Path.fromOSString(pathTokens[i])); + } + } + } + } + return (IPath[])ins.toArray(new IPath[ins.size()]); + } + + /* (non-Javadoc) + * Memory-safe way to access the list of input orders + */ + private Vector getInputOrderList() { + if (inputOrderList == null) { + inputOrderList = new Vector(); + } + return inputOrderList; + } + + /* (non-Javadoc) + * Memory-safe way to access the list of input orders + */ + private Vector getAdditionalInputList() { + if (additionalInputList == null) { + additionalInputList = new Vector(); + } + return additionalInputList; + } + + + /* + * M O D E L A T T R I B U T E A C C E S S O R S + */ + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.core.IInputType#getSuperClass() + */ + public IInputType getSuperClass() { + return superClass; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputType#getName() + */ + public String getName() { + return (name == null && superClass != null) ? superClass.getName() : name; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputType#getBuildVariable() + */ + public String getBuildVariable() { + if (buildVariable == null) { + // If I have a superClass, ask it + if (superClass != null) { + return superClass.getBuildVariable(); + } else { + if (getMultipleOfType()) { + // Use default name + String name = getName(); + if (name == null || name.length() == 0) { + name = getId(); + } + String defaultName = name.toUpperCase(); + defaultName = defaultName.replaceAll("\\W", "_"); //$NON-NLS-1$ //$NON-NLS-2$ + defaultName += "_INPUTS"; //$NON-NLS-1$ + return defaultName; + } else { + return EMPTY_STRING; + } + } + } + return buildVariable; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputType#setBuildVariable() + */ + public void setBuildVariable(String variableName) { + if (variableName == null && buildVariable == null) return; + if (buildVariable == null || variableName == null || !(variableName.equals(buildVariable))) { + buildVariable = variableName; + setDirty(true); + } + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputType#getDependencyContentType() + */ + public IContentType getDependencyContentType() { + if (dependencyContentType == null) { + if (superClass != null) { + return superClass.getDependencyContentType(); + } else { + return null; + } + } + return dependencyContentType; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputType#setDependencyContentType() + */ + public void setDependencyContentType(IContentType type) { + if (dependencyContentType != type) { + dependencyContentType = type; + if (dependencyContentType != null) { + dependencyContentTypeId = dependencyContentType.getId(); + } else { + dependencyContentTypeId = null; + } + setDirty(true); + } + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputType#getDependencyExtensionsAttribute() + */ + public String[] getDependencyExtensionsAttribute() { + if (dependencyExtensions == null || dependencyExtensions.size() == 0) { + // If I have a superClass, ask it + if (superClass != null) { + return superClass.getDependencyExtensionsAttribute(); + } else { + if (dependencyExtensions == null) { + dependencyExtensions = new ArrayList(); + } + } + } + return (String[])dependencyExtensions.toArray(new String[dependencyExtensions.size()]); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputType#setDependencyExtensionsAttribute() + */ + public void setDependencyExtensionsAttribute(String extensions) { + getDependencyExtensionsList().clear(); + if (extensions != null) { + StringTokenizer tokenizer = new StringTokenizer(extensions, DEFAULT_SEPARATOR); + while (tokenizer.hasMoreElements()) { + getDependencyExtensionsList().add(tokenizer.nextElement()); + } + } + setDirty(true); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputType#getDependencyExtensions() + */ + public String[] getDependencyExtensions() { + // Use content type if specified and registered with Eclipse + IContentType type = getDependencyContentType(); + if (type != null) { + return type.getFileSpecs(IContentType.FILE_EXTENSION_SPEC); + } + return getDependencyExtensionsAttribute(); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IInputType#isDependencyExtension() + */ + public boolean isDependencyExtension(String ext) { + String[] exts = getDependencyExtensions(); + for (int i=0; i 0) { + superClass = ManagedBuildManager.getExtensionInputType(superClassId); + if (superClass == null) { + // Report error + ManagedBuildManager.OutputResolveError( + "superClass", //$NON-NLS-1$ + superClassId, + "inputType", //$NON-NLS-1$ + getId()); + } + } + + // Resolve content types + IContentTypeManager manager = Platform.getContentTypeManager(); + if (sourceContentTypeId != null && sourceContentTypeId.length() > 0) { + sourceContentType = manager.getContentType(sourceContentTypeId); + } + if (dependencyContentTypeId != null && dependencyContentTypeId.length() > 0) { + dependencyContentType = manager.getContentType(dependencyContentTypeId); + } + + // Call resolveReferences on our children + Iterator typeIter = getInputOrderList().iterator(); + while (typeIter.hasNext()) { + InputOrder current = (InputOrder)typeIter.next(); + current.resolveReferences(); + } + typeIter = getAdditionalInputList().iterator(); + while (typeIter.hasNext()) { + AdditionalInput current = (AdditionalInput)typeIter.next(); + current.resolveReferences(); + } + } + } + +} diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ManagedBuildInfo.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ManagedBuildInfo.java index 53996255055..3146ee3a142 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ManagedBuildInfo.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ManagedBuildInfo.java @@ -308,7 +308,7 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo { ITool[] tools = getDefaultConfiguration().getFilteredTools(); for (int index = 0; index < tools.length; ++index) { if(tools[index].buildsFileType(sourceExtension)) { - return tools[index].getDependencyGenerator(); + return tools[index].getDependencyGeneratorForExtension(sourceExtension); } } } @@ -663,7 +663,7 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo { } /* (non-Javadoc) - * @see org.eclipse.cdt.core.build.managed.IManagedBuildInfo#getToolInvocation(java.lang.String) + * @see org.eclipse.cdt.core.build.managed.IManagedBuildInfo#getToolForConfiguration(java.lang.String) */ public String getToolForConfiguration(String extension) { // Treat a null argument as an empty string @@ -678,6 +678,38 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo { } return null; } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IManagedBuildInfo#getToolFromInputExtension(java.lang.String) + */ + public ITool getToolFromInputExtension(String sourceExtension) { + // Get all the tools for the current config + ITool[] tools = getFilteredTools(); + for (int index = 0; index < tools.length; index++) { + ITool tool = tools[index]; + if (tool.buildsFileType(sourceExtension)) { + return tool; + } + } + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IManagedBuildInfo#getToolFromOutputExtension(java.lang.String) + */ + public ITool getToolFromOutputExtension(String extension) { + // Treat a null argument as an empty string + String ext = extension == null ? new String() : extension; + // Get all the tools for the current config + ITool[] tools = getFilteredTools(); + for (int index = 0; index < tools.length; index++) { + ITool tool = tools[index]; + if (tool.producesFileType(ext)) { + return tool; + } + } + return null; + } /* (non-Javadoc) * @see org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo#generateCommandLineInfo(java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String[]) diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Option.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Option.java index a5a1ee7d41a..e3cead1a2ff 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Option.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Option.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2004 IBM Corporation and others. + * Copyright (c) 2003, 2005 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at @@ -1146,8 +1146,15 @@ public class Option extends BuildObject implements IOption { * @see org.eclipse.cdt.core.build.managed.IOption#setCategory(org.eclipse.cdt.core.build.managed.IOptionCategory) */ public void setCategory(IOptionCategory category) { - this.category = category; - setDirty(true); + if (this.category != category) { + this.category = category; + if (category != null) { + categoryId = category.getId(); + } else { + categoryId = null; + } + setDirty(true); + } } /* (non-Javadoc) diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/OutputType.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/OutputType.java new file mode 100644 index 00000000000..d7f9ed7b597 --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/OutputType.java @@ -0,0 +1,824 @@ +/********************************************************************** + * Copyright (c) 2005 Intel Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Intel Corporation - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.managedbuilder.internal.core; + +import org.eclipse.core.runtime.content.*; +import org.eclipse.cdt.managedbuilder.core.IBuildObject; +import org.eclipse.cdt.managedbuilder.core.IProjectType; +import org.eclipse.cdt.managedbuilder.core.ITool; +import org.eclipse.cdt.managedbuilder.core.IInputType; +import org.eclipse.cdt.managedbuilder.core.IOutputType; +import org.eclipse.cdt.managedbuilder.core.IManagedOutputNameProvider; +import org.eclipse.cdt.managedbuilder.core.IManagedConfigElement; +import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.Platform; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +public class OutputType extends BuildObject implements IOutputType { + + private static final String DEFAULT_SEPARATOR = ","; //$NON-NLS-1$ + private static final String EMPTY_STRING = new String(); + + // Superclass + private IOutputType superClass; + private String superClassId; + // Parent and children + private ITool parent; + // Managed Build model attributes + private String outputContentTypeId; + private IContentType outputContentType; + private String outputs; + private String optionId; + private String buildVariable; + private Boolean multipleOfType; + private String primaryInputTypeId; + private IInputType primaryInputType; + private Boolean primaryOutput; + private String outputPrefix; + private String outputNames; + private String namePattern; + private IConfigurationElement nameProviderElement = null; + private IManagedOutputNameProvider nameProvider = null; + // Miscellaneous + private boolean isExtensionOutputType = false; + private boolean isDirty = false; + private boolean resolved = true; + + /* + * C O N S T R U C T O R S + */ + + /** + * This constructor is called to create an OutputType defined by an extension point in + * a plugin manifest file, or returned by a dynamic element provider + * + * @param parent The ITool parent of this OutputType + * @param element The OutputType definition from the manifest file or a dynamic element + * provider + */ + public OutputType(ITool parent, IManagedConfigElement element) { + this.parent = parent; + isExtensionOutputType = true; + + // setup for resolving + resolved = false; + + loadFromManifest(element); + + // Hook me up to the Managed Build Manager + ManagedBuildManager.addExtensionOutputType(this); + } + + /** + * This constructor is called to create an OutputType whose attributes will be + * set by separate calls. + * + * @param Tool The parent of the an OutputType + * @param OutputType The superClass, if any + * @param String The id for the new OutputType + * @param String The name for the new OutputType + * @param boolean Indicates whether this is an extension element or a managed project element + */ + public OutputType(Tool parent, IOutputType superClass, String Id, String name, boolean isExtensionElement) { + this.parent = parent; + this.superClass = superClass; + if (this.superClass != null) { + superClassId = this.superClass.getId(); + } + setId(Id); + setName(name); + isExtensionOutputType = isExtensionElement; + if (isExtensionElement) { + // Hook me up to the Managed Build Manager + ManagedBuildManager.addExtensionOutputType(this); + } else { + setDirty(true); + } + } + + /** + * Create an OutputType based on the specification stored in the + * project file (.cdtbuild). + * + * @param parent The ITool the OutputType will be added to. + * @param element The XML element that contains the OutputType settings. + */ + public OutputType(ITool parent, Element element) { + this.parent = parent; + isExtensionOutputType = false; + + // Initialize from the XML attributes + loadFromProject(element); + } + + /** + * Create an OutputType based upon an existing OutputType. + * + * @param parent The ITool the OutputType will be added to. + * @param Id The identifier of the new OutputType + * @param name The name of the new OutputType + * @param outputType The existing OutputType to clone. + */ + public OutputType(ITool parent, String Id, String name, OutputType outputType) { + this.parent = parent; + superClass = outputType.superClass; + if (superClass != null) { + if (outputType.superClassId != null) { + superClassId = new String(outputType.superClassId); + } + } + setId(Id); + setName(name); + isExtensionOutputType = false; + + // Copy the remaining attributes + if (outputType.outputContentTypeId != null) { + outputContentTypeId = new String(outputType.outputContentTypeId); + } + outputContentType = outputType.outputContentType; + if (outputType.outputs != null) { + outputs = new String(outputType.outputs); + } + if (outputType.optionId != null) { + optionId = new String(outputType.optionId); + } + if (outputType.buildVariable != null) { + buildVariable = new String(outputType.buildVariable); + } + if (outputType.multipleOfType != null) { + multipleOfType = new Boolean(outputType.multipleOfType.booleanValue()); + } + if (outputType.primaryInputTypeId != null) { + primaryInputTypeId = new String(outputType.primaryInputTypeId); + } + primaryInputType = outputType.primaryInputType; + if (outputType.primaryOutput != null) { + primaryOutput = new Boolean(outputType.primaryOutput.booleanValue()); + } + if (outputType.outputPrefix != null) { + outputPrefix = new String(outputType.outputPrefix); + } + if (outputType.outputNames != null) { + outputNames = new String(outputType.outputNames); + } + if (outputType.namePattern != null) { + namePattern = new String(outputType.namePattern); + } + + nameProviderElement = outputType.nameProviderElement; + nameProvider = outputType.nameProvider; + + setDirty(true); + } + + /* + * E L E M E N T A T T R I B U T E R E A D E R S A N D W R I T E R S + */ + + /* (non-Javadoc) + * Loads the OutputType information from the ManagedConfigElement specified in the + * argument. + * + * @param element Contains the OutputType information + */ + protected void loadFromManifest(IManagedConfigElement element) { + ManagedBuildManager.putConfigElement(this, element); + + // id + setId(element.getAttribute(IBuildObject.ID)); + + // Get the name + setName(element.getAttribute(IBuildObject.NAME)); + + // superClass + superClassId = element.getAttribute(IProjectType.SUPERCLASS); + + // outputContentType + outputContentTypeId = element.getAttribute(IOutputType.OUTPUT_CONTENT_TYPE); + + // outputs + outputs = element.getAttribute(IOutputType.OUTPUTS); + + // option + optionId = element.getAttribute(IOutputType.OPTION); + + // multipleOfType + String isMOT = element.getAttribute(IOutputType.MULTIPLE_OF_TYPE); + if (isMOT != null){ + multipleOfType = new Boolean("true".equals(isMOT)); //$NON-NLS-1$ + } + + // primaryInputType + primaryInputTypeId = element.getAttribute(IOutputType.PRIMARY_INPUT_TYPE); + + // primaryOutput + String isPO = element.getAttribute(IOutputType.PRIMARY_OUTPUT); + if (isPO != null){ + primaryOutput = new Boolean("true".equals(isPO)); //$NON-NLS-1$ + } + + // outputPrefix + outputPrefix = element.getAttribute(IOutputType.OUTPUT_PREFIX); + + // outputNames + outputNames = element.getAttribute(IOutputType.OUTPUT_NAMES); + + // namePattern + namePattern = element.getAttribute(IOutputType.NAME_PATTERN); + + // buildVariable + buildVariable = element.getAttribute(IOutputType.BUILD_VARIABLE); + + // Store the configuration element IFF there is a name provider defined + String nameProvider = element.getAttribute(IOutputType.NAME_PROVIDER); + if (nameProvider != null && element instanceof DefaultManagedConfigElement) { + nameProviderElement = ((DefaultManagedConfigElement)element).getConfigurationElement(); + } + } + + /* (non-Javadoc) + * Initialize the OutputType information from the XML element + * specified in the argument + * + * @param element An XML element containing the OutputType information + */ + protected void loadFromProject(Element element) { + + // id + setId(element.getAttribute(IBuildObject.ID)); + + // name + if (element.hasAttribute(IBuildObject.NAME)) { + setName(element.getAttribute(IBuildObject.NAME)); + } + + // superClass + superClassId = element.getAttribute(IProjectType.SUPERCLASS); + if (superClassId != null && superClassId.length() > 0) { + superClass = ManagedBuildManager.getExtensionOutputType(superClassId); + if (superClass == null) { + // TODO: Report error + } + } + + // outputContentType + if (element.hasAttribute(IOutputType.OUTPUT_CONTENT_TYPE)) { + outputContentTypeId = element.getAttribute(IOutputType.OUTPUT_CONTENT_TYPE); + } + + // outputs + if (element.hasAttribute(IOutputType.OUTPUTS)) { + outputs = element.getAttribute(IOutputType.OUTPUTS); + } + + // option + if (element.hasAttribute(IOutputType.OPTION)) { + optionId = element.getAttribute(IOutputType.OPTION); + } + + // multipleOfType + if (element.hasAttribute(IOutputType.MULTIPLE_OF_TYPE)) { + String isMOT = element.getAttribute(IOutputType.MULTIPLE_OF_TYPE); + if (isMOT != null){ + multipleOfType = new Boolean("true".equals(isMOT)); //$NON-NLS-1$ + } + } + + // primaryInputType + if (element.hasAttribute(IOutputType.PRIMARY_INPUT_TYPE)) { + primaryInputTypeId = element.getAttribute(IOutputType.PRIMARY_INPUT_TYPE); + primaryInputType = parent.getInputTypeById(primaryInputTypeId); + } + + // primaryOutput + if (element.hasAttribute(IOutputType.PRIMARY_OUTPUT)) { + String isPO = element.getAttribute(IOutputType.PRIMARY_OUTPUT); + if (isPO != null){ + primaryOutput = new Boolean("true".equals(isPO)); //$NON-NLS-1$ + } + } + + // outputPrefix + if (element.hasAttribute(IOutputType.OUTPUT_PREFIX)) { + outputPrefix = element.getAttribute(IOutputType.OUTPUT_PREFIX); + } + + // outputNames + if (element.hasAttribute(IOutputType.OUTPUT_NAMES)) { + outputNames = element.getAttribute(IOutputType.OUTPUT_NAMES); + } + + // namePattern + if (element.hasAttribute(IOutputType.NAME_PATTERN)) { + namePattern = element.getAttribute(IOutputType.NAME_PATTERN); + } + + // buildVariable + if (element.hasAttribute(IOutputType.BUILD_VARIABLE)) { + buildVariable = element.getAttribute(IOutputType.BUILD_VARIABLE); + } + + // Note: Name Provider cannot be specified in a project file because + // an IConfigurationElement is needed to load it! + if (element.hasAttribute(IOutputType.NAME_PROVIDER)) { + // TODO: Issue warning? + } + } + + /** + * Persist the OutputType to the project file. + * + * @param doc + * @param element + */ + public void serialize(Document doc, Element element) { + if (superClass != null) + element.setAttribute(IProjectType.SUPERCLASS, superClass.getId()); + + element.setAttribute(IBuildObject.ID, id); + + if (name != null) { + element.setAttribute(IBuildObject.NAME, name); + } + + if (outputContentTypeId != null) { + element.setAttribute(IOutputType.OUTPUT_CONTENT_TYPE, outputContentTypeId); + } + + if (outputs != null) { + element.setAttribute(IOutputType.OUTPUTS, outputs); + } + + if (optionId != null) { + element.setAttribute(IOutputType.OPTION, optionId); + } + + if (multipleOfType != null) { + element.setAttribute(IOutputType.MULTIPLE_OF_TYPE, multipleOfType.toString()); + } + + if (primaryInputTypeId != null) { + element.setAttribute(IOutputType.PRIMARY_INPUT_TYPE, primaryInputTypeId); + } + + if (primaryOutput != null) { + element.setAttribute(IOutputType.PRIMARY_OUTPUT, primaryOutput.toString()); + } + + if (outputPrefix != null) { + element.setAttribute(IOutputType.OUTPUT_PREFIX, outputPrefix); + } + + if (outputNames != null) { + element.setAttribute(IOutputType.OUTPUT_NAMES, outputNames); + } + + if (namePattern != null) { + element.setAttribute(IOutputType.NAME_PATTERN, namePattern); + } + + if (buildVariable != null) { + element.setAttribute(IOutputType.BUILD_VARIABLE, buildVariable); + } + + // Note: dependency generator cannot be specified in a project file because + // an IConfigurationElement is needed to load it! + if (nameProviderElement != null) { + // TODO: issue warning? + } + + // I am clean now + isDirty = false; + } + + /* + * P A R E N T A N D C H I L D H A N D L I N G + */ + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IOutputType#getParent() + */ + public ITool getParent() { + return parent; + } + + /* + * M O D E L A T T R I B U T E A C C E S S O R S + */ + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.core.IOutputType#getSuperClass() + */ + public IOutputType getSuperClass() { + return superClass; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IOutputType#getName() + */ + public String getName() { + return (name == null && superClass != null) ? superClass.getName() : name; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IOutputType#getBuildVariable() + */ + public String getBuildVariable() { + if (buildVariable == null) { + // If I have a superClass, ask it + if (superClass != null) { + return superClass.getBuildVariable(); + } else { + // Use default name + String name = getName(); + if (name == null || name.length() == 0) { + name = getId(); + } + String defaultName = name.toUpperCase(); + defaultName = defaultName.replaceAll("\\W", "_"); //$NON-NLS-1$ //$NON-NLS-2$ + defaultName += "_OUTPUTS"; //$NON-NLS-1$ + return defaultName; + } + } + return buildVariable; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IOutputType#setBuildVariable() + */ + public void setBuildVariable(String variableName) { + if (variableName == null && buildVariable == null) return; + if (buildVariable == null || variableName == null || !(variableName.equals(buildVariable))) { + buildVariable = variableName; + setDirty(true); + } + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IOutputType#getMultipleOfType() + */ + public boolean getMultipleOfType() { + if (multipleOfType == null) { + if (superClass != null) { + return superClass.getMultipleOfType(); + } else { + return false; // default is false + } + } + return multipleOfType.booleanValue(); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IOuputType#setMultipleOfType() + */ + public void setMultipleOfType(boolean b) { + if (multipleOfType == null || !(b == multipleOfType.booleanValue())) { + multipleOfType = new Boolean(b); + setDirty(true); + } + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IOuputType#getNamePattern() + */ + public String getNamePattern() { + if (namePattern == null) { + // If I have a superClass, ask it + if (superClass != null) { + return superClass.getNamePattern(); + } else { + return EMPTY_STRING; + } + } + return namePattern; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IOuputType#setNamePattern() + */ + public void setNamePattern(String pattern) { + if (pattern == null && namePattern == null) return; + if (namePattern == null || pattern == null || !(pattern.equals(namePattern))) { + namePattern = pattern; + setDirty(true); + } + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IOuputType#getNameProviderElement() + */ + public IConfigurationElement getNameProviderElement() { + if (nameProviderElement == null) { + if (superClass != null) { + return superClass.getNameProviderElement(); + } + } + return nameProviderElement; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IOuputType#setNameProviderElement() + */ + public void setNameProviderElement(IConfigurationElement element) { + nameProviderElement = element; + setDirty(true); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IOuputType#setNameProviderElement() + */ + public IManagedOutputNameProvider getNameProvider() { + if (nameProvider != null) { + return nameProvider; + } + IConfigurationElement element = getNameProviderElement(); + if (element != null) { + try { + if (element.getAttribute(NAME_PROVIDER) != null) { + nameProvider = (IManagedOutputNameProvider) element.createExecutableExtension(NAME_PROVIDER); + return nameProvider; + } + } catch (CoreException e) {} + } + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IOuputType#getOptionId() + */ + public String getOptionId() { + if (optionId == null) { + if (superClass != null) { + return superClass.getOptionId(); + } else { + return null; + } + } + return optionId; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IOuputType#setOptionId() + */ + public void setOptionId(String id) { + if (id == null && optionId == null) return; + if (id == null || optionId == null || !(optionId.equals(id))) { + optionId = id; + setDirty(true); + } + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IOuputType#getOutputContentType() + */ + public IContentType getOutputContentType() { + if (outputContentType == null) { + if (superClass != null) { + return superClass.getOutputContentType(); + } else { + return null; + } + } + return outputContentType; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IOuputType#setOutputContentType() + */ + public void setOutputContentType(IContentType type) { + if (outputContentType != type) { + outputContentType = type; + if (outputContentType != null) { + outputContentTypeId = outputContentType.getId(); + } else { + outputContentTypeId = null; + } + setDirty(true); + } + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IOuputType#getOutputExtensionsAttribute() + */ + public String[] getOutputExtensionsAttribute() { + if (outputs == null) { + if (superClass != null) { + return superClass.getOutputExtensionsAttribute(); + } else { + return null; + } + } + return outputs.split(DEFAULT_SEPARATOR); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IOuputType#setOutputExtensionsAttribute() + */ + public void setOutputExtensionsAttribute(String exts) { + if (exts == null && outputs == null) return; + if (outputs == null || exts == null || !(exts.equals(outputs))) { + outputs = exts; + setDirty(true); + } + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IOuputType#getOutputExtensions() + */ + public String[] getOutputExtensions() { + // Use content type if specified and registered with Eclipse + IContentType type = getOutputContentType(); + if (type != null) { + return type.getFileSpecs(IContentType.FILE_EXTENSION_SPEC); + } + return getOutputExtensionsAttribute(); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IOutputType#isOutputExtension() + */ + public boolean isOutputExtension(String ext) { + String[] exts = getOutputExtensions(); + for (int i=0; i 0) { + superClass = ManagedBuildManager.getExtensionOutputType(superClassId); + if (superClass == null) { + // Report error + ManagedBuildManager.OutputResolveError( + "superClass", //$NON-NLS-1$ + superClassId, + "outputType", //$NON-NLS-1$ + getId()); + } + } + + // Resolve content types + IContentTypeManager manager = Platform.getContentTypeManager(); + if (outputContentTypeId != null && outputContentTypeId.length() > 0) { + outputContentType = manager.getContentType(outputContentTypeId); + } + + // Resolve primary input type + if (primaryInputTypeId != null && primaryInputTypeId.length() > 0) { + primaryInputType = parent.getInputTypeById(primaryInputTypeId); + } + } + } + +} diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/PluginResources.properties b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/PluginResources.properties index 1aff3c32449..08ade51f11f 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/PluginResources.properties +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/PluginResources.properties @@ -47,28 +47,36 @@ ManagedBuildManager.error.open_failed_title=Managed Make Project File Error ManagedBuildManager.error.open_failed=The Managed Make project file could not be read because of the following error.\n\n{0}\n\nManaged Make functionality will not be available for this project. ManagedBuildManager.error.project.version.error=The version number of the project {0} is greater than the Managed Build System version number. ManagedBuildManager.error.id.nomatch=Error loading Managed Make project information for project {0}. The tool definitions used to create the project are not available. - # Makefile Generator Messages MakefileGenerator.message.start.file=Building file: MakefileGenerator.message.finish.file=Finished building: MakefileGenerator.message.start.build=Building target: MakefileGenerator.message.finish.build=Finished building target: +MakefileGenerator.message.no.target=No tool found that can build the extension specified with the build arrtifact name MakefileGenerator.message.adding.source.folder=Adding folder {0} to sources MakefileGenerator.message.gen.source.makefile=Generating makefile for source folder {0} MakefileGenerator.message.calc.delta=Calculating the delta for project {0} MakefileGenerator.message.finding.sources=Finding source files in project {0} MakefileGenerator.comment.module.list = Every subdirectory with source files must be described here +MakefileGenerator.comment.module.variables = Add inputs and outputs from these tool invocations to the build variables MakefileGenerator.comment.source.list = All of the sources participating in the build are defined here MakefileGenerator.comment.build.rule = Each subdirectory must supply rules for building sources it contributes +MakefileGenerator.comment.build.toprules = Tool invocations +MakefileGenerator.comment.build.alltarget = All Target +MakefileGenerator.comment.build.toptargets = Other Targets MakefileGenerator.comment.module.make.includes = Include the makefiles for each source subdirectory MakefileGenerator.comment.module.dep.includes = Include automatically-generated dependency list: MakefileGenerator.comment.autodeps=Automatically-generated dependency list: MakefileGenerator.comment.header=Automatically-generated file. Do not edit! MakefileGenerator.error.spaces=Cannot generate makefile for folder with spaces in name MakefileGenerator.warning.no.source=Nothing to build for project {0} +MakefileGenerator.error.no.nameprovider=A nameProvider or outputNames must be specified with multipleType == true ManagedBuildInfo.message.job.init = Initializing path container for {0} ManagedBuildInfo.message.init.ok = Initializing path container succeeded for {0} # Default GNU Makefile Generator messages -GnuMakefileGenerator.message.postproc.dep.file=Verifying contents of dependency file {0} \ No newline at end of file +GnuMakefileGenerator.message.postproc.dep.file=Verifying contents of dependency file {0} + +# Tool strings +Tool.default.announcement=Invoking: \ No newline at end of file diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Target.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Target.java index ef6de8ee68f..f7944e85f03 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Target.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Target.java @@ -1067,7 +1067,7 @@ public class Target extends BuildObject implements ITarget { newTool.setToolCommand(toolRef.getRawToolCommand()); newTool.setOutputPrefix(toolRef.getRawOutputPrefix()); newTool.setOutputFlag(toolRef.getRawOutputFlag()); - newTool.setOutputExtensions(toolRef.getRawOutputExtensions()); + newTool.setOutputsAttribute(toolRef.getRawOutputExtensions()); // Handle ToolReference children (OptionReference) Iterator optRefIter = toolRef.getOptionReferenceList().listIterator(); while (optRefIter.hasNext()) { diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/TargetPlatform.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/TargetPlatform.java index f08985fca58..9a6fd41dc5c 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/TargetPlatform.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/TargetPlatform.java @@ -470,8 +470,11 @@ public class TargetPlatform extends BuildObject implements ITargetPlatform { * @deprecated */ public void setBinaryParserId(String id) { - String[] ids = new String[]{id}; - setBinaryParserList(ids); + if (id == null) { + setBinaryParserList(new String[0]); + } else { + setBinaryParserList(new String[]{id}); + } } /* (non-Javadoc) diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Tool.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Tool.java index b852fbb4548..0ec1a4ea069 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Tool.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/Tool.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2004 IBM Corporation and others. + * Copyright (c) 2003, 2005 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at @@ -14,7 +14,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; -import java.util.ListIterator; import java.util.Map; import java.util.StringTokenizer; import java.util.Vector; @@ -29,11 +28,14 @@ import org.eclipse.cdt.managedbuilder.core.IProjectType; import org.eclipse.cdt.managedbuilder.core.IResourceConfiguration; import org.eclipse.cdt.managedbuilder.core.ITool; import org.eclipse.cdt.managedbuilder.core.IToolChain; +import org.eclipse.cdt.managedbuilder.core.IInputType; +import org.eclipse.cdt.managedbuilder.core.IOutputType; import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.cdt.managedbuilder.core.IManagedCommandLineGenerator; import org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyGenerator; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -47,11 +49,15 @@ import org.w3c.dom.NodeList; public class Tool extends BuildObject implements ITool, IOptionCategory { public static final String DEFAULT_PATTERN = "${COMMAND} ${FLAGS} ${OUTPUT_FLAG}${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}"; //$NON-NLS-1$ + public static final String DEFAULT_CBS_PATTERN = "${COMMAND}"; //$NON-NLS-1$ private static final String DEFAULT_SEPARATOR = ","; //$NON-NLS-1$ private static final IOptionCategory[] EMPTY_CATEGORIES = new IOptionCategory[0]; private static final IOption[] EMPTY_OPTIONS = new IOption[0]; private static final String EMPTY_STRING = new String(); + private static final String[] EMPTY_STRING_ARRAY = new String[0]; + private static final String DEFAULT_ANNOUNCEMENT_PREFIX = "Tool.default.announcement"; //$NON-NLS-1$ + private static final String WHITESPACE = " "; //$NON-NLS-1$ // Superclass private ITool superClass; @@ -63,6 +69,10 @@ public class Tool extends BuildObject implements ITool, IOptionCategory { private List childOptionCategories; private Vector optionList; private Map optionMap; + private Vector inputTypeList; + private Map inputTypeMap; + private Vector outputTypeList; + private Map outputTypeMap; // Managed Build model attributes private String unusedChildren; private Boolean isAbstract; @@ -75,6 +85,9 @@ public class Tool extends BuildObject implements ITool, IOptionCategory { private String outputPrefix; private String errorParserIds; private String commandLinePattern; + private Boolean advancedInputCategory; + private Boolean customBuildStep; + private String announcement; private IConfigurationElement commandLineGeneratorElement = null; private IManagedCommandLineGenerator commandLineGenerator = null; private IConfigurationElement dependencyGeneratorElement = null; @@ -108,7 +121,7 @@ public class Tool extends BuildObject implements ITool, IOptionCategory { // set up the category map addOptionCategory(this); - // Check for optionList + // Load children IManagedConfigElement[] toolElements = element.getChildren(); for (int l = 0; l < toolElements.length; ++l) { IManagedConfigElement toolElement = toolElements[l]; @@ -117,6 +130,12 @@ public class Tool extends BuildObject implements ITool, IOptionCategory { addOption(option); } else if (toolElement.getName().equals(ITool.OPTION_CAT)) { new OptionCategory(this, toolElement); + } else if (toolElement.getName().equals(ITool.INPUT_TYPE)) { + InputType inputType = new InputType(this, toolElement); + addInputType(inputType); + } else if (toolElement.getName().equals(ITool.OUTPUT_TYPE)) { + OutputType outputType = new OutputType(this, toolElement); + addOutputType(outputType); } } } @@ -207,7 +226,7 @@ public class Tool extends BuildObject implements ITool, IOptionCategory { // set up the category map addOptionCategory(this); - // Check for optionList + // Load children NodeList toolElements = element.getChildNodes(); for (int i = 0; i < toolElements.getLength(); ++i) { Node toolElement = toolElements.item(i); @@ -216,6 +235,10 @@ public class Tool extends BuildObject implements ITool, IOptionCategory { addOption(option); } else if (toolElement.getNodeName().equals(ITool.OPTION_CAT)) { new OptionCategory(this, (Element)toolElement); + } else if (toolElement.getNodeName().equals(ITool.INPUT_TYPE)) { + new InputType(this, (Element)toolElement); + } else if (toolElement.getNodeName().equals(ITool.OUTPUT_TYPE)) { + new OutputType(this, (Element)toolElement); } } } @@ -272,6 +295,15 @@ public class Tool extends BuildObject implements ITool, IOptionCategory { if (tool.outputPrefix != null) { outputPrefix = new String(tool.outputPrefix); } + if (tool.advancedInputCategory != null) { + advancedInputCategory = new Boolean(tool.advancedInputCategory.booleanValue()); + } + if (tool.customBuildStep != null) { + customBuildStep = new Boolean(tool.customBuildStep.booleanValue()); + } + if (tool.announcement != null) { + announcement = new String(tool.announcement); + } commandLineGeneratorElement = tool.commandLineGeneratorElement; commandLineGenerator = tool.commandLineGenerator; @@ -280,7 +312,7 @@ public class Tool extends BuildObject implements ITool, IOptionCategory { // Clone the children // Note: This constructor ignores OptionCategories since they should not be - // found on an non-extension tool + // found on an non-extension tool - TODO: This may need to change! if (tool.optionList != null) { Iterator iter = tool.getOptionList().listIterator(); while (iter.hasNext()) { @@ -299,6 +331,42 @@ public class Tool extends BuildObject implements ITool, IOptionCategory { addOption(newOption); } } + if (tool.inputTypeList != null) { + Iterator iter = tool.getInputTypeList().listIterator(); + while (iter.hasNext()) { + InputType inputType = (InputType) iter.next(); + int nnn = ManagedBuildManager.getRandomNumber(); + String subId; + String subName; + if (inputType.getSuperClass() != null) { + subId = inputType.getSuperClass().getId() + "." + nnn; //$NON-NLS-1$ + subName = inputType.getSuperClass().getName(); + } else { + subId = inputType.getId() + "." + nnn; //$NON-NLS-1$ + subName = inputType.getName(); + } + InputType newInputType = new InputType(this, subId, subName, inputType); + addInputType(newInputType); + } + } + if (tool.outputTypeList != null) { + Iterator iter = tool.getOutputTypeList().listIterator(); + while (iter.hasNext()) { + OutputType outputType = (OutputType) iter.next(); + int nnn = ManagedBuildManager.getRandomNumber(); + String subId; + String subName; + if (outputType.getSuperClass() != null) { + subId = outputType.getSuperClass().getId() + "." + nnn; //$NON-NLS-1$ + subName = outputType.getSuperClass().getName(); + } else { + subId = outputType.getId() + "." + nnn; //$NON-NLS-1$ + subName = outputType.getName(); + } + OutputType newOutputType = new OutputType(this, subId, subName, outputType); + addOutputType(newOutputType); + } + } setDirty(true); } @@ -384,6 +452,21 @@ public class Tool extends BuildObject implements ITool, IOptionCategory { // Get command line pattern commandLinePattern = element.getAttribute( ITool.COMMAND_LINE_PATTERN ); + // Get advancedInputCategory + String advInput = element.getAttribute(ITool.ADVANCED_INPUT_CATEGORY); + if (advInput != null){ + advancedInputCategory = new Boolean("true".equals(advInput)); //$NON-NLS-1$ + } + + // Get customBuildStep + String cbs = element.getAttribute(ITool.CUSTOM_BUILD_STEP); + if (cbs != null){ + customBuildStep = new Boolean("true".equals(cbs)); //$NON-NLS-1$ + } + + // Get the announcement text + announcement = element.getAttribute(ITool.ANNOUNCEMENT); + // Store the configuration element IFF there is a command line generator defined String commandLineGenerator = element.getAttribute(COMMAND_LINE_GENERATOR); if (commandLineGenerator != null && element instanceof DefaultManagedConfigElement) { @@ -507,6 +590,27 @@ public class Tool extends BuildObject implements ITool, IOptionCategory { if( element.hasAttribute( ITool.COMMAND_LINE_PATTERN ) ) { commandLinePattern = element.getAttribute( ITool.COMMAND_LINE_PATTERN ); } + + // advancedInputCategory + if (element.hasAttribute(ITool.ADVANCED_INPUT_CATEGORY)) { + String advInput = element.getAttribute(ITool.ADVANCED_INPUT_CATEGORY); + if (advInput != null){ + advancedInputCategory = new Boolean("true".equals(advInput)); //$NON-NLS-1$ + } + } + + // customBuildStep + if (element.hasAttribute(ITool.CUSTOM_BUILD_STEP)) { + String cbs = element.getAttribute(ITool.CUSTOM_BUILD_STEP); + if (cbs != null){ + customBuildStep = new Boolean("true".equals(cbs)); //$NON-NLS-1$ + } + } + + // Get the announcement text + if (element.hasAttribute(ITool.ANNOUNCEMENT)) { + announcement = element.getAttribute(ITool.ANNOUNCEMENT); + } } /** @@ -607,6 +711,21 @@ public class Tool extends BuildObject implements ITool, IOptionCategory { element.setAttribute(ITool.COMMAND_LINE_PATTERN, commandLinePattern); } + // advancedInputCategory + if (advancedInputCategory != null) { + element.setAttribute(ITool.ADVANCED_INPUT_CATEGORY, advancedInputCategory.toString()); + } + + // customBuildStep + if (customBuildStep != null) { + element.setAttribute(ITool.CUSTOM_BUILD_STEP, customBuildStep.toString()); + } + + // announcement text + if (announcement != null) { + element.setAttribute(ITool.ANNOUNCEMENT, announcement); + } + // Serialize my children if (childOptionCategories != null) { Iterator iter = childOptionCategories.listIterator(); @@ -625,6 +744,22 @@ public class Tool extends BuildObject implements ITool, IOptionCategory { element.appendChild(optionElement); option.serialize(doc, optionElement); } + List typeElements = getInputTypeList(); + iter = typeElements.listIterator(); + while (iter.hasNext()) { + InputType type = (InputType) iter.next(); + Element typeElement = doc.createElement(INPUT_TYPE); + element.appendChild(typeElement); + type.serialize(doc, typeElement); + } + typeElements = getOutputTypeList(); + iter = typeElements.listIterator(); + while (iter.hasNext()) { + OutputType type = (OutputType) iter.next(); + Element typeElement = doc.createElement(OUTPUT_TYPE); + element.appendChild(typeElement); + type.serialize(doc, typeElement); + } // Note: command line generator cannot be specified in a project file because // an IConfigurationElement is needed to load it! @@ -674,7 +809,7 @@ public class Tool extends BuildObject implements ITool, IOptionCategory { } /* (non-Javadoc) - * @see org.eclipse.cdt.managedbuilder.core.ITool#createOption(IOption, String, String, boolean) + * @see org.eclipse.cdt.managedbuilder.core.ITool#removeOption(IOption) */ public void removeOption(IOption option) { getOptionList().remove(option); @@ -767,6 +902,165 @@ public class Tool extends BuildObject implements ITool, IOptionCategory { } } } + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.core.ITool#createInputType(IInputType, String, String, boolean) + */ + public IInputType createInputType(IInputType superClass, String Id, String name, boolean isExtensionElement) { + InputType type = new InputType(this, superClass, Id, name, isExtensionElement); + addInputType(type); + setDirty(true); + return type; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.core.ITool#removeInputType(IInputType) + */ + public void removeInputType(IInputType type) { + getInputTypeList().remove(type); + getInputTypeMap().remove(type.getId()); + setDirty(true); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.core.ITool#getInputTypes() + */ + public IInputType[] getInputTypes() { + IInputType[] types = null; + // Merge our input types with our superclass' input types. + if (superClass != null) { + types = superClass.getInputTypes(); + } + // Our options take precedence. + Vector ourTypes = getInputTypeList(); + if (types != null) { + for (int i = 0; i < ourTypes.size(); i++) { + IInputType ourType = (IInputType)ourTypes.get(i); + int j; + for (j = 0; j < types.length; j++) { + if (ourType.getSuperClass().getId().equals(types[j].getId())) { + types[j] = ourType; + break; + } + } + // No Match? Add it. + if (j == types.length) { + IInputType[] newTypes = new IInputType[types.length + 1]; + for (int k = 0; k < types.length; k++) { + newTypes[k] = types[k]; + } + newTypes[j] = ourType; + types = newTypes; + } + } + } else { + types = (IInputType[])ourTypes.toArray(new IInputType[ourTypes.size()]); + } + return types; + } + + private boolean hasInputTypes() { + Vector ourTypes = getInputTypeList(); + if (ourTypes.size() > 0) return true; + return false; + } + + public IInputType getInputTypeById(String id) { + IInputType type = (IInputType)getInputTypeMap().get(id); + if (type == null) { + if (superClass != null) { + return superClass.getInputTypeById(id); + } + } + return type; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.core.ITool#createOutputType(IOutputType, String, String, boolean) + */ + public IOutputType createOutputType(IOutputType superClass, String Id, String name, boolean isExtensionElement) { + OutputType type = new OutputType(this, superClass, Id, name, isExtensionElement); + addOutputType(type); + setDirty(true); + return type; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.core.ITool#removeOutputType(IOutputType) + */ + public void removeOutputType(IOutputType type) { + getOutputTypeList().remove(type); + getOutputTypeMap().remove(type.getId()); + setDirty(true); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.core.ITool#getOutputTypes() + */ + public IOutputType[] getOutputTypes() { + IOutputType[] types = null; + // Merge our output types with our superclass' output types. + if (superClass != null) { + types = superClass.getOutputTypes(); + } + // Our options take precedence. + Vector ourTypes = getOutputTypeList(); + if (types != null) { + for (int i = 0; i < ourTypes.size(); i++) { + IOutputType ourType = (IOutputType)ourTypes.get(i); + int j; + for (j = 0; j < types.length; j++) { + if (ourType.getSuperClass().getId().equals(types[j].getId())) { + types[j] = ourType; + break; + } + } + // No Match? Add it. + if (j == types.length) { + IOutputType[] newTypes = new IOutputType[types.length + 1]; + for (int k = 0; k < types.length; k++) { + newTypes[k] = types[k]; + } + newTypes[j] = ourType; + types = newTypes; + } + } + } else { + types = (IOutputType[])ourTypes.toArray(new IOutputType[ourTypes.size()]); + } + return types; + } + + private boolean hasOutputTypes() { + Vector ourTypes = getOutputTypeList(); + if (ourTypes.size() > 0) return true; + return false; + } + + public IOutputType getPrimaryOutputType() { + IOutputType type = null; + IOutputType[] types = getOutputTypes(); + if (types != null && types.length > 0) { + for (int i=0; i 0) return exts[0]; + } + // If none, use the input extensions specified for the Tool (backwards compatibility) + List extsList = getInputExtensionsAttribute(); + // Use the first entry in the list + if (extsList != null && extsList.size() > 0) return (String)extsList.get(0); + return EMPTY_STRING; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.core.ITool#getPrimaryInputExtensions() + */ + public String[] getPrimaryInputExtensions() { + IInputType type = getPrimaryInputType(); + if (type != null) { + String[] exts = type.getSourceExtensions(); + // Use the first entry in the list + if (exts.length > 0) return exts; + } + // If none, use the input extensions specified for the Tool (backwards compatibility) + List extsList = getInputExtensionsAttribute(); + // Use the first entry in the list + if (extsList != null && extsList.size() > 0) { + return (String[])extsList.toArray(new String[extsList.size()]); + } + return EMPTY_STRING_ARRAY; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.core.ITool#getAllInputExtensions() + */ + public String[] getAllInputExtensions() { + IInputType[] types = getInputTypes(); + if (types != null && types.length > 0) { + List allExts = new ArrayList(); + for (int i=0; i 0) { + return (String[])allExts.toArray(new String[allExts.size()]); + } + } + // If none, use the input extensions specified for the Tool (backwards compatibility) + List extsList = getInputExtensionsAttribute(); + if (extsList != null && extsList.size() > 0) { + return (String[])extsList.toArray(new String[extsList.size()]); + } + return EMPTY_STRING_ARRAY; + } + + public IInputType getPrimaryInputType() { + IInputType type = null; + IInputType[] types = getInputTypes(); + if (types != null && types.length > 0) { + for (int i=0; i 0) { + for (int i=0; i 0) { + List allExts = new ArrayList(); + for (int i=0; i 0) { + return (String[])allExts.toArray(new String[allExts.size()]); + } + } + // If none, use the header extensions specified for the Tool (backwards compatibility) + List extsList = getHeaderExtensionsAttribute(); + if (extsList != null && extsList.size() > 0) { + return (String[])extsList.toArray(new String[extsList.size()]); + } + return EMPTY_STRING_ARRAY; + } + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.core.ITool#getInterfaceExtension() + * @deprecated + */ public List getInterfaceExtensions() { + return getHeaderExtensionsAttribute(); + } + + private List getHeaderExtensionsAttribute() { if (interfaceExtensions == null || interfaceExtensions.size() == 0) { // If I have a superClass, ask it if (superClass != null) { - return superClass.getInterfaceExtensions(); + return ((Tool)superClass).getHeaderExtensionsAttribute(); } else { if (interfaceExtensions == null) { interfaceExtensions = new ArrayList(); @@ -1074,6 +1594,23 @@ public class Tool extends BuildObject implements ITool, IOptionCategory { * @see org.eclipse.cdt.core.build.managed.ITool#getOutputPrefix() */ public String getOutputPrefix() { + // Get the outputPrefix from an OutputType, if any. + IOutputType type = null; + IOutputType[] types = getOutputTypes(); + if (types != null && types.length > 0) { + for (int i=0; i 0) { + List allExts = new ArrayList(); + for (int i=0; i 0) { + return (String[])allExts.toArray(new String[allExts.size()]); + } + } + // If none, use the outputs specified for the Tool (backwards compatibility) + String[] extsList = getOutputsAttribute(); + if (extsList != null && extsList.length > 0) { + return extsList; + } + return EMPTY_STRING_ARRAY; + } + /* (non-Javadoc) * @see org.eclipse.cdt.managedbuilder.core.ITool#getOutputExtensions() + * @deprecated */ public String[] getOutputExtensions() { + return getOutputsAttribute(); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.core.ITool#getOutputsAttribute() + */ + public String[] getOutputsAttribute() { // TODO: Why is this treated differently than inputExtensions? if (outputExtensions == null) { if (superClass != null) { - return superClass.getOutputExtensions(); + return superClass.getOutputsAttribute(); } else { return null; } @@ -1226,12 +1897,34 @@ public class Tool extends BuildObject implements ITool, IOptionCategory { * @see org.eclipse.cdt.core.build.managed.ITool#getOutputExtension(java.lang.String) */ public String getOutputExtension(String inputExtension) { - // Examine the list of input extensions - ListIterator iter = getInputExtensions().listIterator(); - int i = 0; - while (iter.hasNext()) { - if (((String)iter.next()).equals(inputExtension)) { - String[] exts = getOutputExtensions(); + // Search thru the output-types to find one that has a primary input type with this extension + IOutputType[] types = getOutputTypes(); + int i; + if (types != null) { + for (i=0; i 0) { + return exts[0]; + } + } + } + // Does any input type produce this extension? + if (getInputType(inputExtension) != null) { + // Return the first extension of the primary output type + IOutputType outType = getPrimaryOutputType(); + String[] exts = outType.getOutputExtensions(); + if (exts != null && exts.length > 0) { + return exts[0]; + } + } + } + // If no OutputTypes specified, examine the list of input extensions + String[] inputExts = getAllInputExtensions(); + for (i=0; i 0) { + for (int i=0; i Tool * to retrieve the actual value of attributes. These routines do not go to the @@ -859,112 +1092,4 @@ public class ToolReference implements IToolReference { return command; } - /* (non-Javadoc) - * @see org.eclipse.cdt.managedbuilder.core.ITool#createOption() - */ - public IOption createOption(IOption superClass, String Id, String name, boolean b) { - return null; - } - - /* (non-Javadoc) - * @see org.eclipse.cdt.managedbuilder.core.ITool#removeOption() - */ - public void removeOption(IOption o) { - } - - /* (non-Javadoc) - * @see org.eclipse.cdt.core.build.managed.IOptionCategory#getChildCategories() - */ - public IOptionCategory[] getChildCategories() { - return null; - } - - /* (non-Javadoc) - * @see org.eclipse.cdt.managedbuilder.core.ITool#setParent(IBuildObject) - */ - public void setToolParent(IBuildObject newParent) { - if (parent == null) { - // bad reference - return; - } - // Set the parent in the parent of this ToolRefernce, the tool - ((Tool)parent).setToolParent(newParent); - } - - /* (non-Javadoc) - * @see org.eclipse.cdt.managedbuilder.core.ITool#setIsAbstract(boolean) - */ - public void setIsAbstract(boolean b) { - } - - /* (non-Javadoc) - * @see org.eclipse.cdt.core.build.managed.ITool#getParent() - */ - public IBuildObject getParent() { - return owner; - } - - /* (non-Javadoc) - * @see org.eclipse.cdt.core.build.managed.ITool#getCommandLinePattern() - */ - public String getCommandLinePattern() { - if( parent == null ) return new String(); - return parent.getCommandLinePattern(); - } - - /* (non-Javadoc) - * @see org.eclipse.cdt.core.build.managed.ITool#getCommandLinePattern() - */ - public void setCommandLinePattern(String pattern) { - } - - /* (non-Javadoc) - * @see org.eclipse.cdt.core.build.managed.ITool#getCommandLineGenerator() - */ - public IManagedCommandLineGenerator getCommandLineGenerator() { - if( parent == null ) return null; - return parent.getCommandLineGenerator(); - } - - /* (non-Javadoc) - * @see org.eclipse.cdt.core.build.managed.ITool#getCommandLineGenerator() - */ - public IConfigurationElement getCommandLineGeneratorElement() { - return null; - } - - /* (non-Javadoc) - * @see org.eclipse.cdt.core.build.managed.ITool#setCommandLineGenerator(IConfigurationElement) - */ - public void setCommandLineGeneratorElement(IConfigurationElement element) { - } - - /* (non-Javadoc) - * @see org.eclipse.cdt.core.build.managed.ITool#getDependencyGenerator() - */ - public IManagedDependencyGenerator getDependencyGenerator() { - if( parent == null ) return null; - return parent.getDependencyGenerator(); - } - - /* (non-Javadoc) - * @see org.eclipse.cdt.core.build.managed.ITool#getCommandLineGenerator() - */ - public IConfigurationElement getDependencyGeneratorElement() { - return null; - } - - /* (non-Javadoc) - * @see org.eclipse.cdt.core.build.managed.ITool#setCommandLineGenerator(IConfigurationElement) - */ - public void setDependencyGeneratorElement(IConfigurationElement element) { - } - - /* (non-Javadoc) - * @see org.eclipse.cdt.core.build.managed.ITool#getCommandFlags() - */ - public String[] getCommandFlags() throws BuildException { - if( parent == null ) return null; - return parent.getCommandFlags(); - } } diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/IManagedBuilderMakefileGenerator.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/IManagedBuilderMakefileGenerator.java index 98d80cb1dcf..4d48db10746 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/IManagedBuilderMakefileGenerator.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/IManagedBuilderMakefileGenerator.java @@ -92,6 +92,8 @@ public interface IManagedBuilderMakefileGenerator { public String getMakefileName(); /** + * This method initializes the makefile generator + * * @param project * @param info * @param monitor diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/GnuMakefileGenerator.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/GnuMakefileGenerator.java index 6fed9f10264..cbc09e5f59d 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/GnuMakefileGenerator.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/GnuMakefileGenerator.java @@ -20,17 +20,23 @@ import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; -import java.util.List; +import java.util.Map; import java.util.Set; import java.util.Vector; +import java.util.List; +import java.util.ArrayList; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.internal.core.model.Util; import org.eclipse.cdt.managedbuilder.core.BuildException; import org.eclipse.cdt.managedbuilder.core.IConfiguration; import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo; +import org.eclipse.cdt.managedbuilder.core.IManagedOutputNameProvider; +import org.eclipse.cdt.managedbuilder.core.IOption; import org.eclipse.cdt.managedbuilder.core.IResourceConfiguration; import org.eclipse.cdt.managedbuilder.core.ITool; +import org.eclipse.cdt.managedbuilder.core.IInputType; +import org.eclipse.cdt.managedbuilder.core.IOutputType; import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.cdt.managedbuilder.core.IManagedCommandLineGenerator; import org.eclipse.cdt.managedbuilder.core.IManagedCommandLineInfo; @@ -38,6 +44,7 @@ import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin; import org.eclipse.cdt.managedbuilder.internal.core.ManagedMakeMessages; import org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator; import org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyGenerator; +import org.eclipse.cdt.managedbuilder.makegen.gnu.IManagedBuildGnuToolInfo; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; @@ -65,6 +72,7 @@ import org.eclipse.core.runtime.SubProgressMonitor; * * @since 1.2 */ + public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator { /** @@ -217,822 +225,92 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator { protected static final String MESSAGE_FINISH_FILE = ManagedMakeMessages.getResourceString("MakefileGenerator.message.finish.file"); //$NON-NLS-1$ protected static final String MESSAGE_START_BUILD = ManagedMakeMessages.getResourceString("MakefileGenerator.message.start.build"); //$NON-NLS-1$ protected static final String MESSAGE_START_FILE = ManagedMakeMessages.getResourceString("MakefileGenerator.message.start.file"); //$NON-NLS-1$ + protected static final String MESSAGE_NO_TARGET_TOOL = ManagedMakeMessages.getResourceString("MakefileGenerator.message.no.target"); //$NON-NLS-1$ private static final String MOD_INCL = COMMENT + ".module.make.includes"; //$NON-NLS-1$ private static final String MOD_LIST = COMMENT + ".module.list"; //$NON-NLS-1$ + private static final String MOD_VARS = COMMENT + ".module.variables"; //$NON-NLS-1$ private static final String MOD_RULES = COMMENT + ".build.rule"; //$NON-NLS-1$ + private static final String BUILD_TOP = COMMENT + ".build.toprules"; //$NON-NLS-1$ + private static final String ALL_TARGET = COMMENT + ".build.alltarget"; //$NON-NLS-1$ + private static final String BUILD_TARGETS = COMMENT + ".build.toptargets"; //$NON-NLS-1$ private static final String SRC_LISTS = COMMENT + ".source.list"; //$NON-NLS-1$ + private static final String EMPTY_STRING = new String(); private static final String[] EMPTY_STRING_ARRAY = new String[0]; + + private static final String OBJS_MACRO = "OBJS"; //$NON-NLS-1$ + private static final String DEPS_MACRO = "DEPS"; //$NON-NLS-1$ + private static final String MACRO_ADDITION_ADDPREFIX_SUFFIX = "," + WHITESPACE + LINEBREAK; //$NON-NLS-1$ + private static final String MACRO_ADDITION_PREFIX_SUFFIX = "+=" + WHITESPACE + LINEBREAK; //$NON-NLS-1$ + private static final String PREBUILD = "pre-build"; //$NON-NLS-1$ + private static final String MAINBUILD = "main-build"; //$NON-NLS-1$ + private static final String POSTBUILD = "post-build"; //$NON-NLS-1$ // Local variables needed by generator private String buildTargetName; - private Vector buildTools; + private String buildTargetExt; + private ITool[] buildTools; + private boolean[] buildToolsUsed; + private ManagedBuildGnuToolInfo[] gnuToolInfos; private Vector deletedFileList; private Vector deletedDirList; private Vector dependencyMakefiles; - private String extension; private IManagedBuildInfo info; private Vector invalidDirList; private Vector modifiedList; private IProgressMonitor monitor; - private Set outputExtensionsSet; private IProject project; + private IResource[] projectResources; private Vector ruleList; private Vector subdirList; private IPath topBuildDir; + private Set outputExtensionsSet; + // Maps of macro names (String) to values (List) + private HashMap buildSrcVars = new HashMap(); + private HashMap buildOutVars = new HashMap(); + private HashMap topBuildOutVars = new HashMap(); public GnuMakefileGenerator() { super(); } + + + /************************************************************************* + * IManagedBuilderMakefileGenerator M E T H O D S + ************************************************************************/ /* (non-Javadoc) - * Outputs a comment formatted as follows: - * ##### ....... ##### - * # - * ##### ....... ##### + * @see org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator#initialize() + * + * @param project + * @param info + * @param monitor */ - protected StringBuffer addDefaultHeader() { - StringBuffer buffer = new StringBuffer(); - outputCommentLine(buffer); - buffer.append(COMMENT_SYMBOL + WHITESPACE + ManagedMakeMessages.getResourceString(HEADER) + NEWLINE); - outputCommentLine(buffer); - buffer.append(NEWLINE); - return buffer; - } - - /* (non-Javadoc) - * Answers a StringBuffer containing the comment(s) - * for a dependency makefile. - */ - protected StringBuffer addFragmentDependenciesHeader() { - return addDefaultHeader(); - } - - /* (non-Javadoc) - * Answers a StringBuffer containing the comment(s) - * for a fragment makefile. - */ - protected StringBuffer addFragmentMakefileHeader() { - return addDefaultHeader(); - } - - /* (non-javadoc) - */ - private StringBuffer addMacros() { - StringBuffer buffer = new StringBuffer(); - - // Add the ROOT macro - buffer.append("ROOT := .." + NEWLINE); //$NON-NLS-1$ - buffer.append(NEWLINE); - - // include makefile.init supplementary makefile - buffer.append("-include $(ROOT)" + SEPARATOR + MAKEFILE_INIT + NEWLINE); //$NON-NLS-1$ - buffer.append(NEWLINE); - - // Get the clean command from the build model - buffer.append("RM := "); //$NON-NLS-1$ - buffer.append(info.getCleanCommand() + NEWLINE); - buffer.append(NEWLINE); - - // Now add the source providers - buffer.append(COMMENT_SYMBOL + WHITESPACE + ManagedMakeMessages.getResourceString(SRC_LISTS) + NEWLINE); - buffer.append("-include sources.mk" + NEWLINE); //$NON-NLS-1$ - buffer.append("-include $(SUBDIRS:%=%/subdir.mk)" + NEWLINE); //$NON-NLS-1$ - buffer.append("-include objects.mk" + NEWLINE); //$NON-NLS-1$ - buffer.append("-include $(DEPS)" + NEWLINE); //$NON-NLS-1$ - // Include makefile.defs supplemental makefile - buffer.append("-include $(ROOT)" + SEPARATOR + MAKEFILE_DEFS + NEWLINE); //$NON-NLS-1$ - - - return (buffer.append(NEWLINE)); - } - - /* (non-Javadoc) - * Create the pattern rule in the format: - * /%.: $(ROOT)//%. - * @echo 'Building file: $<' - * @echo $@ $< - * @ $@ $< && \ - * echo -n $(@:%.o=%.d) ' /' >> $(@:%.o=%.d) && \ - * -P -MM -MG $< >> $(@:%.o=%.d) - * @echo 'Finished building: $<' - * @echo ' ' - * - * Note that the macros all come from the build model and are - * resolved to a real command before writing to the module - * makefile, so a real command might look something like: - * source1/%.o: $(ROOT)/source1/%.cpp - * @echo 'Building file: $<' - * @echo g++ -g -O2 -c -I/cygdrive/c/eclipse/workspace/Project/headers -o$@ $< - * @ g++ -g -O2 -c -I/cygdrive/c/eclipse/workspace/Project/headers -o$@ $< && \ - * echo -n $(@:%.o=%.d) ' source1/' >> $(@:%.o=%.d) && \ - * g++ -P -MM -MG -g -O2 -c -I/cygdrive/c/eclipse/workspace/Project/headers $< >> $(@:%.o=%.d) - * @echo 'Finished building: $<' - * @echo ' ' - * - * @param relativePath - * @param buffer - * @param resource - */ - private void addRule(String relativePath, StringBuffer buffer, IResource resource) { - String resourceName = getFileName(resource); - String inputExtension = resource.getFileExtension(); - String cmd = info.getToolForSource(inputExtension); - String outputExtension = info.getOutputExtension(inputExtension); - String outflag = null; - String outputPrefix = null; - IManagedDependencyGenerator depGen = info.getDependencyGenerator(inputExtension); - boolean doDepGen = (depGen != null && depGen.getCalculatorType() == IManagedDependencyGenerator.TYPE_COMMAND); - - // If the tool creates a dependency file, add it to the list - if (doDepGen) { - String depFile = relativePath + resourceName + DOT + DEP_EXT; - getDependencyMakefiles().add(depFile); - } - - /* - * fix for PR 70491 - * We need to check if the current resource is LINKED, because - * the default CDT doesn't handle this properly. If it IS linked, - * then we must get the actual location of the resource, rather - * than the relative path. - */ - IPath resourceLocation = resource.getLocation(); - String projectLocation = project.getLocation().toString(); - String resourcePath = null; - String buildRule = null; - String OptDotExt = ""; //$NON-NLS-1$ - boolean isItLinked = false; - - if (outputExtension != "") //$NON-NLS-1$ - OptDotExt = DOT + outputExtension; - - IConfiguration config = info.getDefaultConfiguration(); - - // We need to check whether we have any resource specific build information. - IResourceConfiguration resConfig = null; - if( config != null ) resConfig = config.getResourceConfiguration(resource.getFullPath().toString()); - - // figure out path to use to resource - if(!resourceLocation.toString().startsWith(projectLocation)) { - // it IS linked, so use the actual location - isItLinked = true; - resourcePath = resourceLocation.toString(); - // Need a hardcoded rule, not a pattern rule, as a linked file - // can reside in any path - buildRule = relativePath + resourceName + OptDotExt + COLON + WHITESPACE + resourcePath; - } else { - // use the relative path (not really needed to store per se but in the future someone may want this) - resourcePath = relativePath; - - // The rule and command to add to the makefile - if( resConfig != null) { - buildRule = resourcePath + resourceName + OptDotExt + COLON + WHITESPACE + ROOT + SEPARATOR + resourcePath + resourceName + DOT + inputExtension; - } else { - buildRule = relativePath + WILDCARD + OptDotExt + COLON + WHITESPACE + ROOT + SEPARATOR + resourcePath + WILDCARD + DOT + inputExtension; - } - } // end fix for PR 70491 - - // No duplicates in a makefile - if (getRuleList().contains(buildRule)) { - return; - } - else { - getRuleList().add(buildRule); - } - buffer.append(buildRule + NEWLINE); - buffer.append(TAB + AT + ECHO + WHITESPACE + SINGLE_QUOTE + MESSAGE_START_FILE + WHITESPACE + IN_MACRO + SINGLE_QUOTE + NEWLINE); - - IManagedCommandLineInfo cmdLInfo = null; - String[] inputs; - if( resConfig != null) { - ITool[] tools = resConfig.getTools(); - outflag = tools[0].getOutputFlag(); - outputPrefix = tools[0].getOutputPrefix(); - cmd = tools[0].getToolCommand(); - inputs = new String[1]; inputs[0] = IN_MACRO; - String[] flags = null; - try { - flags = tools[0].getCommandFlags(); - } catch( BuildException ex ) { - // TODO add some routines to catch this - flags = EMPTY_STRING_ARRAY; - } - IManagedCommandLineGenerator cmdLGen = tools[0].getCommandLineGenerator(); - cmdLInfo = cmdLGen.generateCommandLineInfo( tools[0], cmd, flags, outflag, outputPrefix, - OUT_MACRO, inputs, tools[0].getCommandLinePattern() ); - - String buildCmd = cmdLInfo.getCommandLine(); - buffer.append(TAB + AT + ECHO + WHITESPACE + buildCmd + NEWLINE); - buffer.append(TAB + AT + buildCmd); - } else { - String buildFlags = info.getFlagsForSource(inputExtension); - outflag = info.getOutputFlag(outputExtension); - outputPrefix = info.getOutputPrefix(outputExtension); - String[] flags = buildFlags.split( "\\s" ); //$NON-NLS-1$ - inputs = new String[1]; inputs[0] = IN_MACRO; - cmdLInfo = info.generateCommandLineInfo( inputExtension, flags, outflag, outputPrefix, OUT_MACRO, inputs ); - // The command to build - String buildCmd = null; - if( cmdLInfo == null ) buildCmd = cmd + WHITESPACE + buildFlags + WHITESPACE + outflag + WHITESPACE + outputPrefix + OUT_MACRO + WHITESPACE + IN_MACRO; - else buildCmd = cmdLInfo.getCommandLine(); - buffer.append(TAB + AT + ECHO + WHITESPACE + buildCmd + NEWLINE); - buffer.append(TAB + AT + buildCmd); - } - - // determine if there are any deps to calculate - if (doDepGen && depGen.getCalculatorType() == IManagedDependencyGenerator.TYPE_COMMAND) { - buffer.append(WHITESPACE + LOGICAL_AND + WHITESPACE + LINEBREAK); - // get the dep rule out of the generator - String depCmd = depGen.getDependencyCommand(resource, info); - buffer.append(depCmd); - } - - // Say goodbye to the nice user - buffer.append(NEWLINE); - buffer.append(TAB + AT + ECHO + WHITESPACE + SINGLE_QUOTE + MESSAGE_FINISH_FILE + WHITESPACE + IN_MACRO + SINGLE_QUOTE + NEWLINE); - buffer.append(TAB + AT + ECHO + WHITESPACE + SINGLE_QUOTE + WHITESPACE + SINGLE_QUOTE + NEWLINE + NEWLINE); - } - - - /* (non-javadoc) - * Answers a StringBuffer containing all of the sources contributed by - * a container to the build. - * - * @param module - * @return StringBuffer - */ - private StringBuffer addSources(IContainer module) throws CoreException { - // Calculate the new directory relative to the build output - IPath moduleRelativePath = module.getProjectRelativePath(); - String relativePath = moduleRelativePath.toString(); - relativePath += relativePath.length() == 0 ? "" : SEPARATOR; //$NON-NLS-1$ - relativePath = escapeWhitespaces(relativePath); - - // For each tool for the target, lookup the kinds of sources it can handle and - // create a map which will map its extension to a string which holds its list of sources. - HashMap extensionToRuleStringMap = new HashMap(); - - // get the set of output extensions for all tools - Set outputExtensionsSet = getOutputExtensions(); - - // put in rules if the file type is not a generated file - Iterator iter = buildTools.iterator(); - while(iter.hasNext()) { - List extensionsList = ((ITool)iter.next()).getInputExtensions(); - // iterate over all extensions that the tool knows how to handle - Iterator exListIterator = extensionsList.iterator(); - while(exListIterator.hasNext()) { - // create a macro of the form "EXTENSION_SRCS := " - String extensionName = exListIterator.next().toString(); - if(!extensionToRuleStringMap.containsKey(extensionName) && // do we already have a map entry? - !getOutputExtensions().contains(extensionName)) { // is the file generated? - - // Get the name in the proper macro format - StringBuffer macroName = getMacroName(extensionName); - - // there is no entry in the map, so create a buffer for this extension - StringBuffer tempBuffer = new StringBuffer(); - tempBuffer.append(macroName + WHITESPACE + "+=" + WHITESPACE + LINEBREAK); //$NON-NLS-1$ - tempBuffer.append("${addprefix $(ROOT)/" + relativePath + "," + WHITESPACE + LINEBREAK); //$NON-NLS-1$ //$NON-NLS-2$ - - // have to store the buffer in String form as StringBuffer is not a sublcass of Object - extensionToRuleStringMap.put(extensionName, tempBuffer.toString()); - } - } - } - - // String buffers - StringBuffer buffer = new StringBuffer(); - StringBuffer ruleBuffer = new StringBuffer(COMMENT_SYMBOL + WHITESPACE + ManagedMakeMessages.getResourceString(MOD_RULES) + NEWLINE); - - // Visit the resources in this folder - IResource[] resources = module.members(); - IConfiguration config = info.getDefaultConfiguration(); - - IResourceConfiguration resConfig; - - for (int i = 0; i < resources.length; i++) { - IResource resource = resources[i]; - if (resource.getType() == IResource.FILE) { - // Check whether this resource is excluded from build - resConfig = config.getResourceConfiguration(resource.getFullPath().toString()); - if( (resConfig != null) && (resConfig.isExcluded()) ) - continue; - - String ext = resource.getFileExtension(); - if (info.buildsFileType(ext)) { - // look for the extension in the map - StringBuffer bufferForExtension = new StringBuffer(); - if (!extensionToRuleStringMap.containsKey(ext)) { - continue; - } - bufferForExtension.append(extensionToRuleStringMap.get(ext).toString()); - if(bufferForExtension != null && - !getOutputExtensions().contains(bufferForExtension.toString())) { - - bufferForExtension.append(resource.getName() + WHITESPACE + LINEBREAK); - - // re-insert string in the map - extensionToRuleStringMap.put(ext, bufferForExtension.toString()); - - // Try to add the rule for the file - addRule(relativePath, ruleBuffer, resource); - } - } - } - } - - // Write out the source info to the buffer - Collection bufferCollection = extensionToRuleStringMap.values(); - Iterator collectionIterator = bufferCollection.iterator(); - while(collectionIterator.hasNext()) - { - // close off the rule and put two newlines to the buffer - StringBuffer currentBuffer = new StringBuffer(); - currentBuffer.append(collectionIterator.next().toString()); - currentBuffer.append("}" + NEWLINE + NEWLINE); //$NON-NLS-1$ - - // append the contents of the buffer to the master buffer for the whole file - buffer.append(currentBuffer); - } - return buffer.append(ruleBuffer + NEWLINE); - } - - /* (non-javadoc) - * @return - */ - private StringBuffer addSubdirectories() { - StringBuffer buffer = new StringBuffer(); - // Add the comment - buffer.append(COMMENT_SYMBOL + WHITESPACE + ManagedMakeMessages.getResourceString(MOD_LIST) + NEWLINE); - - buffer.append("SUBDIRS := " + LINEBREAK); //$NON-NLS-1$ - - // Get all the module names - Iterator iter = getSubdirList().listIterator(); - while (iter.hasNext()) { - IContainer container = (IContainer) iter.next(); - updateMonitor(ManagedMakeMessages.getFormattedString("MakefileGenerator.message.adding.source.folder", container.getFullPath().toString())); //$NON-NLS-1$ - // Check the special case where the module is the project root - if (container.getFullPath() == project.getFullPath()) { - buffer.append(DOT + WHITESPACE + LINEBREAK); - } else { - IPath path = container.getProjectRelativePath(); - buffer.append(path.toString() + WHITESPACE + LINEBREAK); - } - } - - buffer.append(NEWLINE); - return buffer; - } - - /* (non-javadoc) - * Answers a StringBuffer containing all of the required targets to - * properly build the project. - * - * @return StringBuffer - */ - private StringBuffer addTargets(boolean rebuild) { - StringBuffer buffer = new StringBuffer(); - - // Assemble the information needed to generate the targets - String cmd = info.getToolForConfiguration(extension); - String flags = info.getFlagsForConfiguration(extension); - String outflag = info.getOutputFlag(extension); - String outputPrefix = info.getOutputPrefix(extension); - String prebuildStep = info.getPrebuildStep(); - prebuildStep.trim(); // Remove leading and trailing whitespace (and control characters) - String postbuildStep = info.getPostbuildStep(); - postbuildStep.trim(); // Remove leading and trailing whitespace (and control characters) - String preannouncebuildStep = info.getPreannouncebuildStep(); - String postannouncebuildStep = info.getPostannouncebuildStep(); - String prebuild = "pre-build"; //$NON-NLS-1$ - String mainbuild = "main-build"; //$NON-NLS-1$ - String postbuild = "post-build"; //$NON-NLS-1$ - String targets = rebuild ? "clean all" : "all"; //$NON-NLS-1$ //$NON-NLS-2$ - - // Get all the projects the build target depends on - IProject[] refdProjects = null; + public void initialize(IProject project, IManagedBuildInfo info, IProgressMonitor monitor) { + // Save the project so we can get path and member information + this.project = project; try { - refdProjects = project.getReferencedProjects(); + projectResources = project.members(); } catch (CoreException e) { - // There are 2 exceptions; the project does not exist or it is not open - // and neither conditions apply if we are building for it .... + projectResources = null; } - - // If a prebuild step exists, redefine the all target to be - // all: {pre-build} main-build - // and then reset the "traditional" all target to main-build - // This will allow something meaningful to happen if the generated - // makefile is - // extracted and run standalone via "make all" - // - String defaultTarget = "all:"; //$NON-NLS-1$ - if (prebuildStep.length() > 0) { - - buffer.append(defaultTarget + WHITESPACE); - buffer.append(prebuild + WHITESPACE); - - // Reset defaultTarget for now and for subsequent use, below - defaultTarget = mainbuild; - buffer.append(defaultTarget); - - // Update the defaultTarget, main-build, by adding a colon, which is - // needed below - defaultTarget = defaultTarget.concat(COLON); - buffer.append(NEWLINE + NEWLINE); - } - - // Write out the all target first in case someone just runs make - // all: or mainbuild: - - buffer.append(defaultTarget + WHITESPACE + outputPrefix + buildTargetName); - if (extension.length() > 0) { - buffer.append(DOT + extension); - } - buffer.append(NEWLINE + NEWLINE); - - /* - * The build target may depend on other projects in the workspace. These - * are captured in the deps target: deps: ; - * $(MAKE) [clean all | all]> - */ - Vector managedProjectOutputs = new Vector(refdProjects.length); - if (refdProjects.length > 0) { - boolean addDeps = true; - if (refdProjects != null) { - for (int i = 0; i < refdProjects.length; i++) { - IProject dep = refdProjects[i]; - if (!dep.exists()) continue; - if (addDeps) { - buffer.append("dependents:" + NEWLINE); //$NON-NLS-1$ - addDeps = false; - } - String buildDir = dep.getLocation().toString(); - String depTargets = targets; - if (ManagedBuildManager.manages(dep)) { - // Add the current configuration to the makefile path - IManagedBuildInfo depInfo = ManagedBuildManager.getBuildInfo(dep); - buildDir += SEPARATOR + depInfo.getConfigurationName(); - - // Extract the build artifact to add to the dependency list - String depTarget = depInfo.getBuildArtifactName(); - String depExt = depInfo.getBuildArtifactExtension(); - String depPrefix = depInfo.getOutputPrefix(depExt); - if (depInfo.needsRebuild()) { - depTargets = "clean all"; //$NON-NLS-1$ - } - String dependency = buildDir + SEPARATOR + depPrefix + depTarget; - if (depExt.length() > 0) { - dependency += DOT + depExt; - } - dependency = escapeWhitespaces(dependency); - managedProjectOutputs.add(dependency); - } - buffer.append(TAB + "-cd" + WHITESPACE + escapeWhitespaces(buildDir) + WHITESPACE + LOGICAL_AND + WHITESPACE + "$(MAKE) " + depTargets + NEWLINE); //$NON-NLS-1$ //$NON-NLS-2$ - } - } - buffer.append(NEWLINE); - } - - /* - * Write out the target rule as: - * .: $(OBJS) - * @echo 'Building target: $@' - * $(BUILD_TOOL) $(FLAGS) $(OUTPUT_FLAG)$@ $(OBJS) $(USER_OBJS) $(LIB_DEPS) - * @echo 'Finished building: $@' - * $(MAKE) --no-print-directory post-build //if postbuild step present - */ - buffer.append(outputPrefix + buildTargetName); - if (extension.length() > 0) { - buffer.append(DOT + extension); - } - buffer.append(COLON + WHITESPACE + "$(OBJS)"); //$NON-NLS-1$ - Iterator refIter = managedProjectOutputs.listIterator(); - while (refIter.hasNext()) { - buffer.append(WHITESPACE + (String)refIter.next()); - } - buffer.append(NEWLINE); - buffer.append(TAB + AT + ECHO + WHITESPACE + SINGLE_QUOTE + MESSAGE_START_BUILD + WHITESPACE + OUT_MACRO + SINGLE_QUOTE + NEWLINE); - buffer.append(TAB + cmd + WHITESPACE + flags + WHITESPACE + outflag + WHITESPACE + OUT_MACRO + WHITESPACE + "$(OBJS) $(USER_OBJS) $(LIBS)" + NEWLINE); //$NON-NLS-1$ - buffer.append(TAB + AT + ECHO + WHITESPACE + SINGLE_QUOTE + MESSAGE_FINISH_FILE + WHITESPACE + OUT_MACRO + SINGLE_QUOTE + NEWLINE); - - // If there is a post build step, then add a recursive invocation of MAKE to invoke it after the main build - // Note that $(MAKE) will instantiate in the recusive invocation to the make command that was used to invoke - // the makefile originally - if (postbuildStep.length() > 0) { - buffer.append(TAB + AT + ECHO + WHITESPACE + SINGLE_QUOTE + WHITESPACE + SINGLE_QUOTE + NEWLINE); - buffer.append(TAB + MAKE + WHITESPACE + NO_PRINT_DIR + WHITESPACE + postbuild + NEWLINE); - } - - buffer.append(NEWLINE); - - // Always add a clean target - buffer.append("clean:" + NEWLINE); //$NON-NLS-1$ - buffer.append(TAB - + "-$(RM)" + WHITESPACE + "$(OBJS)" + WHITESPACE + "$(DEPS)" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - + WHITESPACE + outputPrefix + buildTargetName); - if (extension.length() > 0) { - buffer.append(DOT + extension); - } - buffer.append(NEWLINE); - buffer.append(TAB + DASH + AT + ECHO + WHITESPACE + SINGLE_QUOTE - + WHITESPACE + SINGLE_QUOTE + NEWLINE + NEWLINE); - - // Add the prebuild step target, if specified - if (prebuildStep.length() > 0) { - buffer.append(prebuild + COLON + NEWLINE); - if (preannouncebuildStep.length() > 0) { - buffer.append(TAB + DASH + AT + ECHO + WHITESPACE - + SINGLE_QUOTE + preannouncebuildStep + SINGLE_QUOTE - + NEWLINE); - } - buffer.append(TAB + DASH + prebuildStep + NEWLINE); - buffer.append(TAB + DASH + AT + ECHO + WHITESPACE + SINGLE_QUOTE - + WHITESPACE + SINGLE_QUOTE + NEWLINE + NEWLINE); - } - - // Add the postbuild step, if specified - if (postbuildStep.length() > 0) { - buffer.append(postbuild + COLON + NEWLINE); - if (postannouncebuildStep.length() > 0) { - buffer.append(TAB + DASH + AT + ECHO + WHITESPACE - + SINGLE_QUOTE + postannouncebuildStep + SINGLE_QUOTE - + NEWLINE); - } - buffer.append(TAB + DASH + postbuildStep + NEWLINE); - buffer.append(TAB + DASH + AT + ECHO + WHITESPACE + SINGLE_QUOTE - + WHITESPACE + SINGLE_QUOTE + NEWLINE + NEWLINE); - } - - // Add all the eneded dummy and phony targets - buffer.append(".PHONY: all clean dependents"); //$NON-NLS-1$ - if (prebuildStep.length() > 0) { - buffer.append(WHITESPACE + mainbuild + WHITESPACE + prebuild); - } - if (postbuildStep.length() > 0) { - buffer.append(WHITESPACE + postbuild); - } - buffer.append(NEWLINE); - refIter = managedProjectOutputs.listIterator(); - while(refIter.hasNext()) { - buffer.append((String)refIter.next() + COLON + NEWLINE); - } - buffer.append(NEWLINE); - - // Include makefile.targets supplemental makefile - buffer.append("-include $(ROOT)" + SEPARATOR + MAKEFILE_TARGETS + NEWLINE); //$NON-NLS-1$ - - return buffer; - } - - /* (non-Javadoc) - * Answers a StringBuffer containing the comment(s) - * for the top-level makefile. - */ - protected StringBuffer addTopHeader() { - return addDefaultHeader(); - } - - /** - * Adds the container of the argument to the list of folders in the project that - * contribute source files to the build. The resource visitor has already established - * that the build model knows how to build the files. It has also checked that - * the resource is not generated as part of the build. - * - * @param resource - */ - protected void appendBuildSubdirectory(IResource resource) { - IContainer container = resource.getParent(); - // If the path contains a space relative to the project, reject it from the build - if (resource.getProjectRelativePath().toString().indexOf(" ") != -1) { //$NON-NLS-1$ - // Only add the container once - if (!getInvalidDirList().contains(container)) { - getInvalidDirList().add(container); - } - } else { - // Only add the container once - if (!getSubdirList().contains(container)) { - getSubdirList().add(container); - } - } - } - - /** - * Adds the container of the argument to a list of subdirectories that are to be - * deleted. As a result, the directories that are generated for the output - * should be removed as well. - * - * @param resource - */ - protected void appendDeletedSubdirectory(IContainer container) { - // No point in adding a folder if the parent is already there - IContainer parent = container.getParent(); - if (!getDeletedDirList().contains(container) && - !getDeletedDirList().contains(parent)) { - getDeletedDirList().add(container); - } - } - - /** - * If a file is removed from a source folder (either because of a delete - * or move action on the part of the user), the makefilegenerator has to - * remove the dependency makefile along with the old build goal - * - * @param resource - */ - protected void appendDeletedFile(IResource resource) { - // Cache this for now - getDeletedFileList().add(resource); - } - - /** - * Adds the container of the argument to a list of subdirectories that are part - * of an incremental rebuild of the project. The makefile fragments for these - * directories will be regenerated as a result of the build. - * - * @param resource - */ - protected void appendModifiedSubdirectory(IResource resource) { - IContainer container = resource.getParent(); - // If the path contains a space relative to the project, reject it from the build - if (resource.getProjectRelativePath().toString().indexOf(" ") != -1) { //$NON-NLS-1$ - // Only add the container once - if (!getInvalidDirList().contains(container)) { - getInvalidDirList().add(container); - } - } else { - if (!getModifiedList().contains(container)) { - getModifiedList().add(container); - } - } - } - - /* (non-Javadoc) - * @param message - */ - protected void cancel(String message) { - if (monitor != null && !monitor.isCanceled()) { - throw new OperationCanceledException(message); - } - } - - /* (non-Javadoc) - * Check whether the build has been cancelled. Cancellation requests - * propagated to the caller by throwing OperationCanceledException. - * - * @see org.eclipse.core.runtime.OperationCanceledException#OperationCanceledException() - */ - protected void checkCancel() { - if (monitor != null && monitor.isCanceled()) { - throw new OperationCanceledException(); - } - } - - /* (non-Javadoc) - * Return or create the folder needed for the build output. If we are - * creating the folder, set the derived bit to true so the CM system - * ignores the contents. If the resource exists, respect the existing - * derived setting. - * - * @param string - * @return IPath - */ - private IPath createDirectory(String dirName) throws CoreException { - // Create or get the handle for the build directory - IFolder folder = project.getFolder(dirName); - if (!folder.exists()) { - // Make sure that parent folders exist - IPath parentPath = (new Path(dirName)).removeLastSegments(1); - // Assume that the parent exists if the path is empty - if (!parentPath.isEmpty()) { - IFolder parent = project.getFolder(parentPath); - if (!parent.exists()) { - createDirectory(parentPath.toString()); - } - } - - // Now make the requested folder - try { - folder.create(true, true, null); - } - catch (CoreException e) { - if (e.getStatus().getCode() == IResourceStatus.PATH_OCCUPIED) - folder.refreshLocal(IResource.DEPTH_ZERO, null); - else - throw e; - } - - // Make sure the folder is marked as derived so it is not added to CM - if (!folder.isDerived()) { - folder.setDerived(true); - } - } - - return folder.getFullPath(); - } - - /* (non-Javadoc) - * Return or create the makefile needed for the build. If we are creating - * the resource, set the derived bit to true so the CM system ignores - * the contents. If the resource exists, respect the existing derived - * setting. - * - * @param makefilePath - * @return IFile - */ - private IFile createFile(IPath makefilePath) throws CoreException { - // Create or get the handle for the makefile - IWorkspaceRoot root = CCorePlugin.getWorkspace().getRoot(); - IFile newFile = root.getFileForLocation(makefilePath); - if (newFile == null) { - newFile = root.getFile(makefilePath); - } - // Create the file if it does not exist - ByteArrayInputStream contents = new ByteArrayInputStream(new byte[0]); - try { - newFile.create(contents, false, new SubProgressMonitor(monitor, 1)); - // Make sure the new file is marked as derived - if (!newFile.isDerived()) { - newFile.setDerived(true); - } - - } - 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; - } - - return newFile; - } - - /** - * @param deletedFile - */ - private void deleteBuildTarget(IResource deletedFile) { - // Get the project relative path of the file - String fileName = getFileName(deletedFile); - String srcExtension = deletedFile.getFileExtension(); - String targetExtension = info.getOutputExtension(srcExtension); - if (targetExtension != "") //$NON-NLS-1$ - fileName += DOT + targetExtension; - IPath projectRelativePath = deletedFile.getProjectRelativePath().removeLastSegments(1); - IPath targetFilePath = getBuildWorkingDir().append(projectRelativePath).append(fileName); - IResource depFile = project.findMember(targetFilePath); - if (depFile != null && depFile.exists()) { - try { - depFile.delete(true, new SubProgressMonitor(monitor, 1)); - } catch (CoreException e) { - // This had better be allowed during a build - - } - } - } - - /** - * @param deletedFile - */ - private void deleteDepFile(IResource deletedFile) { - // Get the project relative path of the file - String fileName = getFileName(deletedFile); - fileName += DOT + DEP_EXT; - IPath projectRelativePath = deletedFile.getProjectRelativePath().removeLastSegments(1); - IPath depFilePath = getBuildWorkingDir().append(projectRelativePath).append(fileName); - IResource depFile = project.findMember(depFilePath); - if (depFile != null && depFile.exists()) { - try { - depFile.delete(true, new SubProgressMonitor(monitor, 1)); - } catch (CoreException e) { - // This had better be allowed during a build - - } - } - } - - /* (non-Javadoc) - * Answers the argument with all whitespaces replaced with an escape sequence. - * - * @param path - */ - protected String escapeWhitespaces(String path) { - // Escape the spaces in the path/filename if it has any - String[] segments = path.split("\\s"); //$NON-NLS-1$ - if (segments.length > 1) { - StringBuffer escapedPath = new StringBuffer(); - for (int index = 0; index < segments.length; ++index) { - escapedPath.append(segments[index]); - if (index + 1 < segments.length) { - escapedPath.append("\\ "); //$NON-NLS-1$ - } - } - return escapedPath.toString().trim(); - } else { - return path; + // Save the monitor reference for reporting back to the user + this.monitor = monitor; + // Get the build info for the project + this.info = info; + // Get the name of the build target + buildTargetName = info.getBuildArtifactName(); + // Get its extension + buildTargetExt = info.getBuildArtifactExtension(); + if (buildTargetExt == null) { + buildTargetExt = new String(); } + // Cache the build tools + buildTools = info.getDefaultConfiguration().getFilteredTools(); + buildToolsUsed = new boolean[buildTools.length]; + for (int i=0; iString - * - * @param file - * @return - */ - private String getFileName(IResource file) { - String answer = new String(); - String lastSegment = file.getName(); - int extensionSeparator = lastSegment.lastIndexOf(DOT); - if (extensionSeparator != -1) { - answer = lastSegment.substring(0, extensionSeparator); - } - return answer; - } - - /* (non-Javadoc) - * Answers a Vector containing a list of directories that are invalid for the - * build for some reason. At the moment, the only reason a directory would - * not be considered for the build is if it contains a space in the relative - * path from the project root. - * - * @return a a list of directories that are invalid for the build - */ - private Vector getInvalidDirList() { - if (invalidDirList == null) { - invalidDirList = new Vector(); - } - return invalidDirList; - } - - protected StringBuffer getMacroName(String extensionName) { - StringBuffer macroName = new StringBuffer(); - - // We need to handle case sensitivity in file extensions (e.g. .c vs .C), so if the - // extension was already upper case, tack on an "UPPER_" to the macro name. - // In theory this means there could be a conflict if you had for example, - // extensions .c_upper, and .C, but realistically speaking the chances of this are - // practically nil so it doesn't seem worth the hassle of generating a truly - // unique name. - if(extensionName.equals(extensionName.toUpperCase())) { - macroName.append(extensionName.toUpperCase() + "_UPPER"); //$NON-NLS-1$ - } else { - // lower case... no need for "UPPER_" - macroName.append(extensionName.toUpperCase()); - } - macroName.append("_SRCS"); //$NON-NLS-1$ - return macroName; - } /* (non-Javadoc) * @see org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator#getMakefileName() @@ -1311,92 +532,6 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator { return new String(MAKEFILE_NAME); } - /* (non-javadoc) - * - * @return Vector - */ - private Vector getModifiedList() { - if (modifiedList == null) { - modifiedList = new Vector(); - } - return modifiedList; - } - - /* (non-Javadoc) - * Answers all of the output extensions that the ITarget - * of the build has tools defined to work on. - * - * @return a Set containing all of the output extensions - */ - protected Set getOutputExtensions() { - if (outputExtensionsSet == null) { - // The set of output extensions which will be produced by this tool. - // It is presumed that this set is not very large (likely < 10) so - // a HashSet should provide good performance. - outputExtensionsSet = new HashSet(); - - // For each tool for the target, lookup the kinds of sources it outputs - // and add that to our list of output extensions. - Iterator iter = buildTools.iterator(); - while(iter.hasNext()) { - ITool tool = (ITool)iter.next(); - String[] outputs = tool.getOutputExtensions(); - if (outputs != null) { - outputExtensionsSet.addAll(Arrays.asList(outputs)); - } - } - } - return outputExtensionsSet; - } - - /* (non-javadoc) - * Answers the list of known build rules. This keeps me from generating duplicate - * rules for known file extensions. - * - * @return List - */ - private Vector getRuleList() { - if (ruleList == null) { - ruleList = new Vector(); - } - return ruleList; - } - - /* (non-javadoc) - * Answers the list of subdirectories contributing source code to the build - * - * @return List - */ - private Vector getSubdirList() { - if (subdirList == null) { - subdirList = new Vector(); - } - return subdirList; - } - - /** - * @param project - * @param info - * @param monitor - */ - public void initialize(IProject project, IManagedBuildInfo info, IProgressMonitor monitor) { - // Save the project so we can get path and member information - this.project = project; - // Save the monitor reference for reporting back to the user - this.monitor = monitor; - // Get the build info for the project - this.info = info; - // Get the name of the build target - buildTargetName = info.getBuildArtifactName(); - // Get its extension - extension = info.getBuildArtifactExtension(); - if (extension == null) { - extension = new String(); - } - // Cache the build tools - buildTools = new Vector(Arrays.asList(info.getDefaultConfiguration().getFilteredTools())); - } - /* (non-Javadoc) * @see org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator#isGeneratedResource(org.eclipse.core.resources.IResource) */ @@ -1415,14 +550,134 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator { } /* (non-Javadoc) - * Put COLS_PER_LINE comment charaters in the argument. + * @see org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator#regenerateDependencies() */ - protected void outputCommentLine(StringBuffer buffer) { - for (int i = 0; i < COLS_PER_LINE; i++) { - buffer.append(COMMENT_SYMBOL); + public void regenerateDependencies(boolean force) throws CoreException { + // A hack for the pre-3.x GCC compilers is to put dummy targets for deps + IWorkspaceRoot root = CCorePlugin.getWorkspace().getRoot(); + + Iterator iter = getDependencyMakefiles().listIterator(); + while (iter.hasNext()) { + // The path to search for the dependency makefile + IPath relDepFilePath = topBuildDir.append(new Path((String)iter.next())); + IFile depFile = root.getFile(relDepFilePath); + if (depFile == null || !depFile.isAccessible()) continue; + try { + updateMonitor(ManagedMakeMessages.getFormattedString("GnuMakefileGenerator.message.postproc.dep.file", depFile.getName())); //$NON-NLS-1$ + populateDummyTargets(depFile, true); + } catch (CoreException e) { + throw e; + } catch (IOException e) { + // This looks like a problem reading or writing the file + continue; + } } - buffer.append(NEWLINE); } + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator#regenerateMakefiles() + */ + public MultiStatus regenerateMakefiles() throws CoreException { + MultiStatus status; + // Visit the resources in the project + ResourceProxyVisitor visitor = new ResourceProxyVisitor(this, info); + project.accept(visitor, IResource.NONE); + + // See if the user has cancelled the build + checkCancel(); + + // Populate the makefile if any source files have been found in the project + if (getSubdirList().isEmpty()) { + String info = ManagedMakeMessages.getFormattedString("MakefileGenerator.warning.no.source", project.getName()); //$NON-NLS-1$ + updateMonitor(info); + status = new MultiStatus( + ManagedBuilderCorePlugin.getUniqueIdentifier(), + IStatus.INFO, + info, + null); + status.add(new Status ( + IStatus.INFO, + ManagedBuilderCorePlugin.getUniqueIdentifier(), + NO_SOURCE_FOLDERS, + new String(), + null)); + return status; + } + + // Create the top-level directory for the build output + topBuildDir = createDirectory(info.getConfigurationName()); + checkCancel(); + + // Get the list of subdirectories + IPath srcsFilePath = topBuildDir.addTrailingSeparator().append(SRCSFILE_NAME); + IFile srcsFileHandle = createFile(srcsFilePath); + buildSrcVars.clear(); + buildOutVars.clear(); + topBuildOutVars.clear(); + populateSourcesMakefile(srcsFileHandle); + checkCancel(); + + // Now populate the module makefiles + Iterator iter = getSubdirList().listIterator(); + while (iter.hasNext()) { + IContainer subDir = (IContainer)iter.next(); + try { + populateFragmentMakefile(subDir); + } catch (CoreException e) { + // Probably should ask user if they want to continue + checkCancel(); + continue; + } + checkCancel(); + } + + // Calculate the inputs and outputs of the Tools to be generated in the main makefile + calculateToolInputsOutputs(); + checkCancel(); + + // Create the top-level makefile + IPath makefilePath = topBuildDir.addTrailingSeparator().append(MAKEFILE_NAME); + IFile makefileHandle = createFile(makefilePath); + populateTopMakefile(makefileHandle, true); + checkCancel(); + + // Now finish up by adding all the object files + IPath objFilePath = topBuildDir.addTrailingSeparator().append(OBJECTS_MAKFILE); + IFile objsFileHandle = createFile(objFilePath); + populateObjectsMakefile(objsFileHandle); + checkCancel(); + + // How did we do + if (!getInvalidDirList().isEmpty()) { + status = new MultiStatus ( + ManagedBuilderCorePlugin.getUniqueIdentifier(), + IStatus.WARNING, + new String(), + null); + // Add a new status for each of the bad folders + iter = getInvalidDirList().iterator(); + while (iter.hasNext()) { + status.add(new Status ( + IStatus.WARNING, + ManagedBuilderCorePlugin.getUniqueIdentifier(), + SPACES_IN_PATH, + ((IContainer)iter.next()).getFullPath().toString(), + null)); + } + } else { + status = new MultiStatus( + ManagedBuilderCorePlugin.getUniqueIdentifier(), + IStatus.OK, + new String(), + null); + } + return status; + } + + + /************************************************************************* + * M A K E F I L E S P O P U L A T I O N M E T H O D S + ************************************************************************/ protected void populateDummyTargets(IFile makefile, boolean force) throws CoreException, IOException { if (makefile == null || !makefile.exists()) return; @@ -1580,6 +835,10 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator { } /* (non-javadoc) + * This method generates a "fragment" make file (subdir.mk). + * One of these is generated for each project directory/subdirectory + * that contains source files. + * * @param module * @throws CoreException */ @@ -1608,97 +867,58 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator { } /* (non-Javadoc) - * The makefile generator "knows" about source files participating in the - * the build. It does not keep track of the targets that the build produces. - * Instead, it keeps a set of transformation macros that it supplies to the - * makefile so that the source names can be transofrmed into the target names - * using the built-in string substitution functions of make. + * The makefile generator generates a Macro for each type of output, other than final artifact, + * created by the build. * * @param fileHandle The file that should be populated with the output * @throws CoreException */ protected void populateObjectsMakefile(IFile fileHandle) throws CoreException { + // Master list of "object" dependencies, i.e. dependencies between input files and output files. StringBuffer macroBuffer = new StringBuffer(); - macroBuffer.append(addDefaultHeader()); - StringBuffer objectsBuffer = new StringBuffer(); - objectsBuffer.append("OBJS := " + LINEBREAK); //$NON-NLS-1$ - StringBuffer depFilesBuffer = new StringBuffer(); - depFilesBuffer.append("DEPS := " + LINEBREAK); //$NON-NLS-1$ + List valueList; + macroBuffer.append(addDefaultHeader()); + + // Map of macro names (String) to its definition (List of Strings) + HashMap outputMacros = new HashMap(); + + // Add the predefined LIBS, USER_OBJS, & DEPS macros // Add the libraries this project depends on - macroBuffer.append("LIBS := "); //$NON-NLS-1$ - String[] libs = info.getLibsForConfiguration(extension); + valueList = new ArrayList(); + String[] libs = info.getLibsForConfiguration(buildTargetExt); for (int i = 0; i < libs.length; i++) { String string = libs[i]; - macroBuffer.append(LINEBREAK + string); + valueList.add(string); } - macroBuffer.append(NEWLINE); + outputMacros.put("LIBS", valueList); //$NON-NLS-1$ // Add the extra user-specified objects - macroBuffer.append("USER_OBJS := "); //$NON-NLS-1$ - String[] userObjs = info.getUserObjectsForConfiguration(extension); - for (int j = 0; j < userObjs.length; j++) { - String string = userObjs[j]; - macroBuffer.append(LINEBREAK + string); + valueList = new ArrayList(); + String[] userObjs = info.getUserObjectsForConfiguration(buildTargetExt); + for (int i = 0; i < userObjs.length; i++) { + String string = userObjs[i]; + valueList.add(string); } - macroBuffer.append(NEWLINE); + outputMacros.put("USER_OBJS", valueList); //$NON-NLS-1$ - // Dependencies for generated files will not appear here. I.e., if you have a tool which turns - // A into B, and then another tool which turns B into C, you will only get dependency info - // which says that B depends on A. - // TODO Handle dependencies for complex chains of the form A->B->C - - // set of input extensions for which rules have been created so far - HashSet handledInputExtensions = new HashSet(); - - // Look at each input extension and generate an appropriate macro for that extension - // based on whether the file is generated or not. We do not want to create rules for - // generated files due to the current way the makefile is structured. - Iterator iter = buildTools.iterator(); - while(iter.hasNext()) { - ITool tool = (ITool)iter.next(); - List extensionsList = tool.getInputExtensions(); - - // iterate over all extensions that the tool knows how to handle - Iterator exListIterator = extensionsList.iterator(); - while(exListIterator.hasNext()) { - String extensionName = exListIterator.next().toString(); - - // If we are a regular file we get added to the list of object dependencies - // if we have not already created a rule for this filetype. It is assumed that - // if multiple tools can handle the same input file extension that they will - // all map the input extension to the same output extension. This is not explicitly - // checked however. - - // Generated files should not appear in the list. - if(!getOutputExtensions().contains(extensionName) && !handledInputExtensions.contains(extensionName)) { - handledInputExtensions.add(extensionName); - StringBuffer macroName = getMacroName(extensionName); - String OptDotExt = ""; //$NON-NLS-1$ - if (tool.getOutputExtension(extensionName) != "") //$NON-NLS-1$ - OptDotExt = DOT + tool.getOutputExtension(extensionName); - - // create dependency rule of the form - // OBJS = $(macroName1: $(ROOT)/%.input1=%.output1) ... $(macroNameN: $(ROOT)/%.inputN=%.outputN) - objectsBuffer.append(WHITESPACE + "$(" + macroName + COLON + "$(ROOT)" + SEPARATOR + WILDCARD //$NON-NLS-1$ //$NON-NLS-2$ - + DOT + extensionName + "=" + WILDCARD + OptDotExt + ")" ); //$NON-NLS-1$ //$NON-NLS-2$ - - // And another for the deps makefiles - // DEPS = $(macroName1: $(ROOT)/%.input1=%.DEP_EXT) ... $(macroNameN: $(ROOT)/%.inputN=%.DEP_EXT) - depFilesBuffer.append(WHITESPACE + "$(" + macroName + COLON + "$(ROOT)" + SEPARATOR + WILDCARD //$NON-NLS-1$ //$NON-NLS-2$ - + DOT + extensionName + "=" + WILDCARD + DOT + //$NON-NLS-1$ - DEP_EXT + ")" ); //$NON-NLS-1$ - - } - } - } - - macroBuffer.append(NEWLINE + NEWLINE + objectsBuffer); - macroBuffer.append(NEWLINE + NEWLINE + depFilesBuffer); + // Write every macro to the file + Iterator iterator = outputMacros.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = (Map.Entry)iterator.next(); + macroBuffer.append((String)entry.getKey() + " :="); //$NON-NLS-1$ + valueList = (List)entry.getValue(); + Iterator valueIter = valueList.iterator(); + while (valueIter.hasNext()) { + macroBuffer.append(WHITESPACE + (String)valueIter.next()); + } + if (iterator.hasNext()) macroBuffer.append(NEWLINE + NEWLINE); + } // For now, just save the buffer that was populated when the rules were created Util.save(macroBuffer, fileHandle); + } /* (non-Javadoc) @@ -1708,25 +928,63 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator { protected void populateSourcesMakefile(IFile fileHandle) throws CoreException { // Add the comment StringBuffer buffer = addDefaultHeader(); - - // Add the known macros + + // Determine the set of macros HashSet handledInputExtensions = new HashSet(); - Iterator iter = buildTools.iterator(); - while(iter.hasNext()) { - List extensionsList = ((ITool)iter.next()).getInputExtensions(); - Iterator exListIterator = extensionsList.iterator(); - while(exListIterator.hasNext()) { + String buildMacro; + for (int i=0; iStringBuffer containing all of the required targets to + * properly build the project. + * + * @param outputVarsAdditionsList list to add needed build output variables to + * @param rebuild + * @return StringBuffer + */ + private StringBuffer addTargets(List outputVarsAdditionsList, boolean rebuild) { + StringBuffer buffer = new StringBuffer(); + + // Assemble the information needed to generate the targets + String prebuildStep = info.getPrebuildStep(); + prebuildStep.trim(); // Remove leading and trailing whitespace (and control characters) + String postbuildStep = info.getPostbuildStep(); + postbuildStep.trim(); // Remove leading and trailing whitespace (and control characters) + String preannouncebuildStep = info.getPreannouncebuildStep(); + String postannouncebuildStep = info.getPostannouncebuildStep(); + String targets = rebuild ? "clean all" : "all"; //$NON-NLS-1$ //$NON-NLS-2$ + + IConfiguration config = info.getDefaultConfiguration(); + ITool targetTool = config.getTargetTool(); + if (targetTool == null) { + targetTool = info.getToolFromOutputExtension(buildTargetExt); + } + + // Get all the projects the build target depends on + IProject[] refdProjects = null; + try { + refdProjects = project.getReferencedProjects(); + } catch (CoreException e) { + // There are 2 exceptions; the project does not exist or it is not open + // and neither conditions apply if we are building for it .... + } + + // If a prebuild step exists, redefine the all target to be + // all: {pre-build} main-build + // and then reset the "traditional" all target to main-build + // This will allow something meaningful to happen if the generated + // makefile is + // extracted and run standalone via "make all" + // + String defaultTarget = "all:"; //$NON-NLS-1$ + if (prebuildStep.length() > 0) { + + buffer.append(defaultTarget + WHITESPACE); + buffer.append(PREBUILD + WHITESPACE); + + // Reset defaultTarget for now and for subsequent use, below + defaultTarget = MAINBUILD; + buffer.append(defaultTarget); + + // Update the defaultTarget, main-build, by adding a colon, which is + // needed below + defaultTarget = defaultTarget.concat(COLON); + buffer.append(NEWLINE + NEWLINE); + } + + // Write out the all target first in case someone just runs make + // all: or mainbuild: + + // Add the comment + buffer.append(COMMENT_SYMBOL + WHITESPACE + ManagedMakeMessages.getResourceString(ALL_TARGET) + NEWLINE); + + String outputPrefix = EMPTY_STRING; + if (targetTool != null) { + outputPrefix = targetTool.getOutputPrefix(); + } + buffer.append(defaultTarget + WHITESPACE + outputPrefix + buildTargetName); + if (buildTargetExt.length() > 0) { + buffer.append(DOT + buildTargetExt); + } + buffer.append(NEWLINE + NEWLINE); + + /* + * The build target may depend on other projects in the workspace. These + * are captured in the deps target: deps: ; + * $(MAKE) [clean all | all]> + */ + Vector managedProjectOutputs = new Vector(refdProjects.length); + if (refdProjects.length > 0) { + boolean addDeps = true; + if (refdProjects != null) { + for (int i = 0; i < refdProjects.length; i++) { + IProject dep = refdProjects[i]; + if (!dep.exists()) continue; + if (addDeps) { + buffer.append("dependents:" + NEWLINE); //$NON-NLS-1$ + addDeps = false; + } + String buildDir = dep.getLocation().toString(); + String depTargets = targets; + if (ManagedBuildManager.manages(dep)) { + // Add the current configuration to the makefile path + IManagedBuildInfo depInfo = ManagedBuildManager.getBuildInfo(dep); + buildDir += SEPARATOR + depInfo.getConfigurationName(); + + // Extract the build artifact to add to the dependency list + String depTarget = depInfo.getBuildArtifactName(); + String depExt = depInfo.getBuildArtifactExtension(); + String depPrefix = depInfo.getOutputPrefix(depExt); + if (depInfo.needsRebuild()) { + depTargets = "clean all"; //$NON-NLS-1$ + } + String dependency = buildDir + SEPARATOR + depPrefix + depTarget; + if (depExt.length() > 0) { + dependency += DOT + depExt; + } + dependency = escapeWhitespaces(dependency); + managedProjectOutputs.add(dependency); + } + buffer.append(TAB + "-cd" + WHITESPACE + escapeWhitespaces(buildDir) + WHITESPACE + LOGICAL_AND + WHITESPACE + "$(MAKE) " + depTargets + NEWLINE); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + buffer.append(NEWLINE); + } + + // Add the targets tool rules + buffer.append(addTargetsRules(targetTool, + outputVarsAdditionsList, managedProjectOutputs, (postbuildStep.length() > 0))); + + // Add the prebuild step target, if specified + if (prebuildStep.length() > 0) { + buffer.append(PREBUILD + COLON + NEWLINE); + if (preannouncebuildStep.length() > 0) { + buffer.append(TAB + DASH + AT + ECHO + WHITESPACE + + SINGLE_QUOTE + preannouncebuildStep + SINGLE_QUOTE + + NEWLINE); + } + buffer.append(TAB + DASH + prebuildStep + NEWLINE); + buffer.append(TAB + DASH + AT + ECHO + WHITESPACE + SINGLE_QUOTE + + WHITESPACE + SINGLE_QUOTE + NEWLINE + NEWLINE); + } + + // Add the postbuild step, if specified + if (postbuildStep.length() > 0) { + buffer.append(POSTBUILD + COLON + NEWLINE); + if (postannouncebuildStep.length() > 0) { + buffer.append(TAB + DASH + AT + ECHO + WHITESPACE + + SINGLE_QUOTE + postannouncebuildStep + SINGLE_QUOTE + + NEWLINE); + } + buffer.append(TAB + DASH + postbuildStep + NEWLINE); + buffer.append(TAB + DASH + AT + ECHO + WHITESPACE + SINGLE_QUOTE + + WHITESPACE + SINGLE_QUOTE + NEWLINE + NEWLINE); + } + // Add all the needed dummy and phony targets + buffer.append(".PHONY: all clean dependents" + NEWLINE); //$NON-NLS-1$ + buffer.append(".SECONDARY:"); //$NON-NLS-1$ + if (prebuildStep.length() > 0) { + buffer.append(WHITESPACE + MAINBUILD + WHITESPACE + PREBUILD); + } + if (postbuildStep.length() > 0) { + buffer.append(WHITESPACE + POSTBUILD); + } + buffer.append(NEWLINE); + Iterator refIter = managedProjectOutputs.listIterator(); + while(refIter.hasNext()) { + buffer.append((String)refIter.next() + COLON + NEWLINE); + } + buffer.append(NEWLINE); + + // Include makefile.targets supplemental makefile + buffer.append("-include $(ROOT)" + SEPARATOR + MAKEFILE_TARGETS + NEWLINE); //$NON-NLS-1$ + + return buffer; + } + + /* (non-javadoc) + * Returns the targets rules. The targets make file (top makefile) contains: + * 1 the rule for the final target tool + * 2 the rules for all of the tools that use multipleOfType in their primary input type + * 3 the rules for all tools that use the output of #2 tools + * + * @param outputVarsAdditionsList list to add needed build output variables to + * @param managedProjectOutputs Other projects in the workspace that this project depends upon + * @return StringBuffer + */ + private StringBuffer addTargetsRules(ITool targetTool, + List outputVarsAdditionsList, Vector managedProjectOutputs, boolean postbuildStep) { + StringBuffer buffer = new StringBuffer(); + // Add the comment + buffer.append(COMMENT_SYMBOL + WHITESPACE + ManagedMakeMessages.getResourceString(BUILD_TOP) + NEWLINE); + + // Get the target tool and generate the rule + if (targetTool != null) { + if (addRuleForTool(targetTool, buffer, true, buildTargetName, buildTargetExt, + outputVarsAdditionsList, managedProjectOutputs)) { + // Mark the target tool as processed + for (int i=0; i 0) { + buffer.append(DOT + buildTargetExt); + } + buffer.append(NEWLINE); + buffer.append(TAB + DASH + AT + ECHO + WHITESPACE + SINGLE_QUOTE + + WHITESPACE + SINGLE_QUOTE + NEWLINE + NEWLINE); + + return buffer; + } + + /* (non-Javadoc) + * Create the rule + * + * @param tool + * @param buffer Buffer to add makefile rules to + * @param bTargetTool True if this is the target tool + * @param targetName If this is the "targetTool", the target file name, else null + * @param targetName If this is the "targetTool", the target file extension, else null + * @param outputVarsAdditionsList list to add needed build output variables to + * @param managedProjectOutputs Other projects in the workspace that this project depends upon + */ + protected boolean addRuleForTool(ITool tool, StringBuffer buffer, boolean bTargetTool, String targetName, String targetExt, + List outputVarsAdditionsList, Vector managedProjectOutputs) { + + // Get the tool's inputs and outputs + Vector inputs = new Vector(); + Vector dependencies = new Vector(); + Vector outputs = new Vector(); + Vector enumeratedOutputs = new Vector(); + Vector outputVariables = new Vector(); + String outputPrefix = EMPTY_STRING; + if (!getToolInputsOutputs(tool, inputs, dependencies, outputs, enumeratedOutputs, outputVariables, + bTargetTool, managedProjectOutputs)) { + return false; + } + + // Add the output variables for this tool to our list + outputVarsAdditionsList.addAll(outputVariables); + + // Create the build rule + String buildRule = EMPTY_STRING; + String outflag = tool.getOutputFlag(); + + Iterator iter = enumeratedOutputs.listIterator(); + boolean first = true; + while(iter.hasNext()) { + String output = (String)iter.next(); + if (!first) buildRule += WHITESPACE; + first = false; + buildRule += output; + } + buildRule += (COLON + WHITESPACE); + iter = inputs.listIterator(); + first = true; + iter = dependencies.listIterator(); + while(iter.hasNext()) { + String input = (String)iter.next(); + if (!first) buildRule += WHITESPACE; + first = false; + buildRule += input; + } + + // We can't have duplicates in a makefile + if (getRuleList().contains(buildRule)) { + return true; + } + else { + getRuleList().add(buildRule); + } + buffer.append(buildRule + NEWLINE); + if (bTargetTool) { + buffer.append(TAB + AT + ECHO + WHITESPACE + SINGLE_QUOTE + MESSAGE_START_BUILD + WHITESPACE + OUT_MACRO + SINGLE_QUOTE + NEWLINE); + } + buffer.append(TAB + AT + ECHO + WHITESPACE + SINGLE_QUOTE + tool.getAnnouncement() + SINGLE_QUOTE + NEWLINE); + + // Get the command line for this tool invocation + String[] flags; + try { + flags = tool.getCommandFlags(); + } catch( BuildException ex ) { + // TODO report error + flags = EMPTY_STRING_ARRAY; + } + String[] cmdInputs = (String[])inputs.toArray(new String[inputs.size()]); + IManagedCommandLineGenerator gen = tool.getCommandLineGenerator(); + IManagedCommandLineInfo cmdLInfo = gen.generateCommandLineInfo( tool, tool.getToolCommand(), + flags, outflag, outputPrefix, OUT_MACRO, cmdInputs, tool.getCommandLinePattern() ); + // The command to build + String buildCmd = null; + if( cmdLInfo == null ) { + String toolFlags; + try { + toolFlags = tool.getToolFlags(); + } catch( BuildException ex ) { + // TODO report error + toolFlags = EMPTY_STRING; + } + buildCmd = tool.getToolCommand() + WHITESPACE + toolFlags + WHITESPACE + outflag + WHITESPACE + outputPrefix + OUT_MACRO + WHITESPACE + IN_MACRO; + } + else buildCmd = cmdLInfo.getCommandLine(); + buffer.append(TAB + AT + ECHO + WHITESPACE + buildCmd + NEWLINE); + buffer.append(TAB + AT + buildCmd); + + // TODO + // NOTE WELL: Dependency file generation is not handled for this type of Tool + + // Echo finished message + buffer.append(NEWLINE); + if (bTargetTool) { + buffer.append(TAB + AT + ECHO + WHITESPACE + SINGLE_QUOTE + MESSAGE_FINISH_BUILD + WHITESPACE + OUT_MACRO + SINGLE_QUOTE + NEWLINE); + } else { + buffer.append(TAB + AT + ECHO + WHITESPACE + SINGLE_QUOTE + MESSAGE_FINISH_FILE + WHITESPACE + OUT_MACRO + SINGLE_QUOTE + NEWLINE); + } + buffer.append(TAB + AT + ECHO + WHITESPACE + SINGLE_QUOTE + WHITESPACE + SINGLE_QUOTE + NEWLINE + NEWLINE); + return true; + } + + /* (non-Javadoc) + * @param outputVarsAdditionsList list to add needed build output variables to + * @param buffer buffer to add rules to + */ + private void generateRulesForConsumers(ITool generatingTool, List outputVarsAdditionsList, StringBuffer buffer) { + // Generate a build rule for any tool that consumes the output of this tool + IOutputType[] outTypes = generatingTool.getOutputTypes(); + for (int i=0; iStringBuffer containing the comment(s) + * for a fragment makefile (subdir.mk). + */ + protected StringBuffer addFragmentMakefileHeader() { + return addDefaultHeader(); + } + + /* (non-javadoc) + * Returns a StringBuffer containing makefile text for all of the sources + * contributed by a container (project directory/subdirectory) to the fragement makefile + * + * @param module project resource directory/subdirectory + * @return StringBuffer generated text for the fragement makefile + */ + protected StringBuffer addSources(IContainer module) throws CoreException { + // Calculate the new directory relative to the build output + IPath moduleRelativePath = module.getProjectRelativePath(); + String relativePath = moduleRelativePath.toString(); + relativePath += relativePath.length() == 0 ? "" : SEPARATOR; //$NON-NLS-1$ + relativePath = escapeWhitespaces(relativePath); + + // For build macros in the configuration, create a map which will map them + // to a string which holds its list of sources. + HashMap buildVarToRuleStringMap = new HashMap(); + + // Add statements that add the source files in this folder, + // and generated source files, and generated dependency files + // to the build macros + Iterator iterator = buildSrcVars.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = (Map.Entry)iterator.next(); + String macroName = (String)entry.getKey(); + addMacroAdditionPrefix(buildVarToRuleStringMap, macroName, "$(ROOT)/" + relativePath, true); //$NON-NLS-1$ + } + iterator = buildOutVars.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = (Map.Entry)iterator.next(); + String macroName = (String)entry.getKey(); + addMacroAdditionPrefix(buildVarToRuleStringMap, macroName, "./" + relativePath, true); + } + // Create an entry for the DEPS macro + addMacroAdditionPrefix(buildVarToRuleStringMap, DEPS_MACRO, "./" + relativePath, true); + + // String buffers + StringBuffer buffer = new StringBuffer(); // Return buffer + StringBuffer ruleBuffer = new StringBuffer(COMMENT_SYMBOL + WHITESPACE + ManagedMakeMessages.getResourceString(MOD_RULES) + NEWLINE); + + // Visit the resources in this folder and add each one to a sources macro, and generate a build rule, if appropriate + IResource[] resources = module.members(); + IConfiguration config = info.getDefaultConfiguration(); + + IResourceConfiguration resConfig; + IFolder folder = project.getFolder(info.getConfigurationName()); + + for (int i = 0; i < resources.length; i++) { + IResource resource = resources[i]; + if (resource.getType() == IResource.FILE) { + // Check whether this resource is excluded from build + resConfig = config.getResourceConfiguration(resource.getFullPath().toString()); + if( (resConfig != null) && (resConfig.isExcluded()) ) + continue; + addFragmentMakefileEntriesForSource(buildVarToRuleStringMap, ruleBuffer, + folder, relativePath, resource, null, false); + } + } + + // Write out the macro addition entries to the buffer + buffer.append(writeAdditionMacros(buildVarToRuleStringMap, true)); + return buffer.append(ruleBuffer + NEWLINE); + } + + /* (non-Javadoc + * Adds the entries for a particular source file to the fragment makefile + * + * @param buildVarToRuleStringMap map of build variable names to the list of files assigned to the variable + * @param ruleBuffer buffer to add generated nmakefile text to + * @param folder the top level build output directory + * @param relativePath build output directory relative path of the current output directory + * @param resource the source file for this invocation of the tool + * @param macroName the build variable to add this invocation's outputs to + * if null, use the file extension to find the name + */ + protected void addFragmentMakefileEntriesForSource (HashMap buildVarToRuleStringMap, StringBuffer ruleBuffer, + IFolder folder, String relativePath, IResource resource, String varName, boolean generatedSource) { + // Determine which tool, if any, builds files with this extension + String ext = resource.getFileExtension(); + for (int j=0; j 0) { + addMacroAdditionFile(buildVarToRuleStringMap, DEPS_MACRO, generatedDepFile.toString()); + } + + // If the generated outputs of this tool are input to another tool, + // 1. add the output to the appropriate macro + // 2. If the tool does not have multipleOfType input, generate the rule. + + IOutputType outType = tool.getPrimaryOutputType(); + String buildVariable = null; + if (outType != null) { + buildVariable = outType.getBuildVariable(); + } else { + // For support of pre-CDT 3.0 integrations. + buildVariable = OBJS_MACRO; //$NON-NLS-1$ + } + Vector generatedOutputs = calculateOutputsForSource(tool, relativePath, resource); + for (int k=0; k/%.: $(ROOT)//%. + * @echo 'Building file: $<' + * @echo $@ $< + * @ $@ $< && \ + * echo -n $(@:%.o=%.d) ' /' >> $(@:%.o=%.d) && \ + * -P -MM -MG $< >> $(@:%.o=%.d) + * @echo 'Finished building: $<' + * @echo ' ' + * + * Note that the macros all come from the build model and are + * resolved to a real command before writing to the module + * makefile, so a real command might look something like: + * source1/%.o: $(ROOT)/source1/%.cpp + * @echo 'Building file: $<' + * @echo g++ -g -O2 -c -I/cygdrive/c/eclipse/workspace/Project/headers -o$@ $< + * @ g++ -g -O2 -c -I/cygdrive/c/eclipse/workspace/Project/headers -o$@ $< && \ + * echo -n $(@:%.o=%.d) ' source1/' >> $(@:%.o=%.d) && \ + * g++ -P -MM -MG -g -O2 -c -I/cygdrive/c/eclipse/workspace/Project/headers $< >> $(@:%.o=%.d) + * @echo 'Finished building: $<' + * @echo ' ' + * + * @param relativePath build output directory relative path of the current output directory + * @param buffer buffer to populate with the build rule + * @param resource the source file for this invocation of the tool + * @param generatedSource true if the resource is a generated output + * @param generatedDepFile passed in as an empty string; append the dependency file name + * to it if one is generated by the rule */ - public MultiStatus regenerateMakefiles() throws CoreException { - MultiStatus status; - // Visit the resources in the project - ResourceProxyVisitor visitor = new ResourceProxyVisitor(this, info); - project.accept(visitor, IResource.NONE); + protected void addRuleForSource(String relativePath, StringBuffer buffer, IResource resource, + boolean generatedSource, StringBuffer generatedDepFile) { - // See if the user has cancelled the build - checkCancel(); + String resourceName = getFileName(resource); + String inputExtension = resource.getFileExtension(); + String cmd = info.getToolForSource(inputExtension); + String outputExtension = info.getOutputExtension(inputExtension); + String outflag = null; + String outputPrefix = null; + IManagedDependencyGenerator depGen = info.getDependencyGenerator(inputExtension); + boolean doDepGen = (depGen != null && depGen.getCalculatorType() == IManagedDependencyGenerator.TYPE_COMMAND); - // Populate the makefile if any source files have been found in the project - if (getSubdirList().isEmpty()) { - String info = ManagedMakeMessages.getFormattedString("MakefileGenerator.warning.no.source", project.getName()); //$NON-NLS-1$ - updateMonitor(info); - status = new MultiStatus( - ManagedBuilderCorePlugin.getUniqueIdentifier(), - IStatus.INFO, - info, - null); - status.add(new Status ( - IStatus.INFO, - ManagedBuilderCorePlugin.getUniqueIdentifier(), - NO_SOURCE_FOLDERS, - new String(), - null)); - return status; - } - - // Create the top-level directory for the build output - topBuildDir = createDirectory(info.getConfigurationName()); - checkCancel(); - - // Get the list of subdirectories - IPath srcsFilePath = topBuildDir.addTrailingSeparator().append(SRCSFILE_NAME); - IFile srcsFileHandle = createFile(srcsFilePath); - populateSourcesMakefile(srcsFileHandle); - checkCancel(); - - // Now populate the module makefiles - Iterator iter = getSubdirList().listIterator(); - while (iter.hasNext()) { - IContainer subDir = (IContainer)iter.next(); - try { - populateFragmentMakefile(subDir); - } catch (CoreException e) { - // Probably should ask user if they want to continue - checkCancel(); - continue; - } - checkCancel(); + // If the tool creates a dependency file, add it to the list + if (doDepGen) { + String depFile = relativePath + resourceName + DOT + DEP_EXT; + getDependencyMakefiles().add(depFile); + generatedDepFile.append(depFile); } - - // Create the top-level makefile - IPath makefilePath = topBuildDir.addTrailingSeparator().append(MAKEFILE_NAME); - IFile makefileHandle = createFile(makefilePath); - populateTopMakefile(makefileHandle, true); - checkCancel(); + + /* + * fix for PR 70491 + * We need to check if the current resource is LINKED, because + * the default CDT doesn't handle this properly. If it IS linked, + * then we must get the actual location of the resource, rather + * than the relative path. + */ + IPath resourceLocation = resource.getLocation(); + String projectLocation = project.getLocation().toString(); + String resourcePath = null; + String buildRule = null; + String OptDotExt = ""; //$NON-NLS-1$ + boolean isItLinked = false; - // Now finish up by adding all the object files - IPath objFilePath = topBuildDir.addTrailingSeparator().append(OBJECTS_MAKFILE); - IFile objsFileHandle = createFile(objFilePath); - populateObjectsMakefile(objsFileHandle); - checkCancel(); + if (outputExtension != "") //$NON-NLS-1$ + OptDotExt = DOT + outputExtension; - // How did we do - if (!getInvalidDirList().isEmpty()) { - status = new MultiStatus ( - ManagedBuilderCorePlugin.getUniqueIdentifier(), - IStatus.WARNING, - new String(), - null); - // Add a new status for each of the bad folders - iter = getInvalidDirList().iterator(); - while (iter.hasNext()) { - status.add(new Status ( - IStatus.WARNING, - ManagedBuilderCorePlugin.getUniqueIdentifier(), - SPACES_IN_PATH, - ((IContainer)iter.next()).getFullPath().toString(), - null)); + IConfiguration config = info.getDefaultConfiguration(); + + // We need to check whether we have any resource specific build information. + IResourceConfiguration resConfig = null; + if( config != null ) resConfig = config.getResourceConfiguration(resource.getFullPath().toString()); + + // figure out path to use to resource + if(!resourceLocation.toString().startsWith(projectLocation)) { + // it IS linked, so use the actual location + isItLinked = true; + resourcePath = resourceLocation.toString(); + // Need a hardcoded rule, not a pattern rule, as a linked file + // can reside in any path + buildRule = relativePath + resourceName + OptDotExt + COLON + WHITESPACE + resourcePath; + } else { + // use the relative path (not really needed to store per se but in the future someone may want this) + resourcePath = relativePath; + + // The rule and command to add to the makefile + String home = (generatedSource)? DOT : ROOT; + if( resConfig != null) { + buildRule = resourcePath + resourceName + OptDotExt + COLON + WHITESPACE + home + SEPARATOR + resourcePath + resourceName + DOT + inputExtension; + } else { + buildRule = relativePath + WILDCARD + OptDotExt + COLON + WHITESPACE + home + SEPARATOR + resourcePath + WILDCARD + DOT + inputExtension; + } + } // end fix for PR 70491 + + // Add any additional dependencies specified: + // 1. in additionalInput elements + // 2. from a dependency calculator not of TYPE_COMMAND + ITool tool; + if( resConfig != null) { + ITool[] tools = resConfig.getTools(); + tool = tools[0]; + } else { + tool = info.getToolFromInputExtension(inputExtension); + } + // Get any additional dependencies specified for the tool + IPath[] addlDepPaths = tool.getAdditionalDependencies(); + for (int i=0; iIPaths for this invocation of the tool with the specified source file + /* + * The priorities for determining the names of the outputs of a tool are: + * 1. If the tool is the build target and primary output, use artifact name & extension - + * This case does not apply here... + * 2. If an option is specified, use the value of the option + * 3. If a nameProvider is specified, call it + * 4. If outputNames is specified, use it + * 5. Use the name pattern to generate a transformation macro + * so that the source names can be transformed into the target names + * using the built-in string substitution functions of make. + * + * @param tool + * @param relativePath build output directory relative path of the current output directory + * @param resource + * @return Vector of IPaths that are relative to the build directory + */ + protected Vector calculateOutputsForSource(ITool tool, String relativePath, IResource resource) { + Vector outputs = new Vector(); + String inExt = resource.getFileExtension(); + String outExt = tool.getOutputExtension(inExt); + + IOutputType[] outTypes = tool.getOutputTypes(); + if (outTypes != null && outTypes.length > 0) { + for (int i=0; i 0) { + for (int j=0; jmake. + if (multOfType) { + // This case is not handled - a nameProvider or outputNames must be specified + // TODO - report error + } else { + String namePattern = type.getNamePattern(); + if (namePattern == null || namePattern.length() == 0) { + namePattern = outputPrefix + IManagedBuilderMakefileGenerator.WILDCARD; + } + else if (outputPrefix.length() > 0) { + namePattern = outputPrefix + namePattern; + } + if (outExt != null && outExt.length() > 0) { + namePattern += DOT + outExt; + } + + // Get the input file name + String fileName = resource.getFullPath().removeFileExtension().lastSegment(); + // Replace the % with the file name + String outName = namePattern.replaceAll("%", fileName); //$NON-NLS-1$ + IPath outPath = Path.fromOSString(outName); + outputs.add(outPath); + } + } } } else { - status = new MultiStatus( - ManagedBuilderCorePlugin.getUniqueIdentifier(), - IStatus.OK, - new String(), - null); + // For support of pre-CDT 3.0 integrations. + // NOTE WELL: This only supports the case of a single "target tool" + // that consumes exactly all of the object files, $OBJS, produced + // by other tools in the build and produces a single output. + // In this case, the output file name is the input file name with + // the output extension. + + IPath outPath = resource.getFullPath().removeFileExtension(); + String outPrefix = tool.getOutputPrefix(); + if (outPrefix.length() > 0) { + String outName = outPrefix + outPath.lastSegment(); + outPath = outPath.removeLastSegments(1).append(outName); + } + outPath = outPath.addFileExtension(outExt); + outputs.add(outPath); } - return status; + + return outputs; + } + + /* (non-Javadoc) + * Returns the dependency IPaths for this invocation of the tool with the specified source file + * + * @param depGen the dependency calculator + * @param tool tool used to build the source file + * @param relativePath build output directory relative path of the current output directory + * @param resource source file to scan for dependencies + * @return Vector of IPaths that are relative to the build directory + */ + protected Vector calculateDependenciesForSource(IManagedDependencyGenerator depGen, ITool tool, String relativePath, IResource resource) { + Vector deps = new Vector(); + int type = depGen.getCalculatorType(); + + switch (type) { + + case IManagedDependencyGenerator.TYPE_INDEXER: + case IManagedDependencyGenerator.TYPE_EXTERNAL: + IResource[] res = depGen.findDependencies(resource, project); + for (int i=0; iSet containing all of the output extensions + */ + public Set getOutputExtensions() { + if (outputExtensionsSet == null) { + // The set of output extensions which will be produced by this tool. + // It is presumed that this set is not very large (likely < 10) so + // a HashSet should provide good performance. + outputExtensionsSet = new HashSet(); + + // For each tool for the target, lookup the kinds of sources it outputs + // and add that to our list of output extensions. + for (int i=0; i + * ##### ....... ##### + */ + protected StringBuffer addDefaultHeader() { + StringBuffer buffer = new StringBuffer(); + outputCommentLine(buffer); + buffer.append(COMMENT_SYMBOL + WHITESPACE + ManagedMakeMessages.getResourceString(HEADER) + NEWLINE); + outputCommentLine(buffer); + buffer.append(NEWLINE); + return buffer; + } + + /* (non-Javadoc) + * Put COLS_PER_LINE comment charaters in the argument. + */ + protected void outputCommentLine(StringBuffer buffer) { + for (int i = 0; i < COLS_PER_LINE; i++) { + buffer.append(COMMENT_SYMBOL); + } + buffer.append(NEWLINE); + } + + /* (non-Javadoc) + * Answers the argument with all whitespaces replaced with an escape sequence. + * + * @param path + */ + protected String escapeWhitespaces(String path) { + // Escape the spaces in the path/filename if it has any + String[] segments = path.split("\\s"); //$NON-NLS-1$ + if (segments.length > 1) { + StringBuffer escapedPath = new StringBuffer(); + for (int index = 0; index < segments.length; ++index) { + escapedPath.append(segments[index]); + if (index + 1 < segments.length) { + escapedPath.append("\\ "); //$NON-NLS-1$ + } + } + return escapedPath.toString().trim(); + } else { + return path; + } + } + + /* (non-Javadoc) + * Adds a macro addition prefix to a map of macro names to entries. + * Entry prefixes look like: + * C_SRCS += \ + * ${addprefix $(ROOT)/, \ + */ + protected void addMacroAdditionPrefix(HashMap map, String macroName, String relativePath, boolean addPrefix) { + // there is no entry in the map, so create a buffer for this macro + StringBuffer tempBuffer = new StringBuffer(); + tempBuffer.append(macroName + WHITESPACE + MACRO_ADDITION_PREFIX_SUFFIX); //$NON-NLS-1$ + if (addPrefix) { + tempBuffer.append("${addprefix " + relativePath + MACRO_ADDITION_ADDPREFIX_SUFFIX); //$NON-NLS-1$ //$NON-NLS-2$ + } + + // have to store the buffer in String form as StringBuffer is not a sublcass of Object + map.put(macroName, tempBuffer.toString()); + } + + /* (non-Javadoc) + * Adds a file to an entry in a map of macro names to entries. + * File additions look like: + * example.c, \ + */ + protected void addMacroAdditionFile(HashMap map, String macroName, String filename) { + StringBuffer buffer = new StringBuffer(); + buffer.append(map.get(macroName)); + buffer.append(filename + WHITESPACE + LINEBREAK); + // re-insert string in the map + map.put(macroName, buffer.toString()); + } + + /* (non-Javadoc) + * Adds file(s) to an entry in a map of macro names to entries. + * File additions look like: + * example.c, \ + */ + public void addMacroAdditionFiles(HashMap map, String macroName, Vector filenames) { + StringBuffer buffer = new StringBuffer(); + buffer.append(map.get(macroName)); + for (int i=0; i 0) { + buffer.append(filename + WHITESPACE + LINEBREAK); + } + } + // re-insert string in the map + map.put(macroName, buffer.toString()); + } + + /* (non-Javadoc) + * Write all macro addition entries in a map to the buffer + */ + protected StringBuffer writeAdditionMacros(HashMap map, boolean addPrefix) { + StringBuffer buffer = new StringBuffer(); + // Add the comment + buffer.append(COMMENT_SYMBOL + WHITESPACE + ManagedMakeMessages.getResourceString(MOD_VARS) + NEWLINE); + + Collection bufferCollection = map.values(); + Iterator collectionIterator = bufferCollection.iterator(); + while(collectionIterator.hasNext()) + { + String macroString = collectionIterator.next().toString(); + // Check if we added any files to the rule + // Currently, we do this by comparing the end of the rule buffer to MACRO_ADDITION_PREFIX_SUFFIX + if (!(macroString.endsWith(MACRO_ADDITION_PREFIX_SUFFIX)) && + !(macroString.endsWith(MACRO_ADDITION_ADDPREFIX_SUFFIX))) { + StringBuffer currentBuffer = new StringBuffer(); + currentBuffer.append( macroString); + // Close off the rule + if (addPrefix) { + currentBuffer.append("}"); //$NON-NLS-1$ + } + currentBuffer.append(NEWLINE); + + // append the contents of the buffer to the master buffer for the whole file + buffer.append(currentBuffer); + } + } + return buffer.append(NEWLINE); + } + + /* (non-Javadoc) + * Write all macro addition entries in a map to the buffer + */ + protected StringBuffer writeTopAdditionMacros(List varList, HashMap varMap) { + StringBuffer buffer = new StringBuffer(); + // Add the comment + buffer.append(COMMENT_SYMBOL + WHITESPACE + ManagedMakeMessages.getResourceString(MOD_VARS) + NEWLINE); + + for (int i=0; iOperationCanceledException. + * + * @see org.eclipse.core.runtime.OperationCanceledException#OperationCanceledException() + */ + protected void checkCancel() { + if (monitor != null && monitor.isCanceled()) { + throw new OperationCanceledException(); + } + } + + /* (non-Javadoc) + * Return or create the folder needed for the build output. If we are + * creating the folder, set the derived bit to true so the CM system + * ignores the contents. If the resource exists, respect the existing + * derived setting. + * + * @param string + * @return IPath + */ + private IPath createDirectory(String dirName) throws CoreException { + // Create or get the handle for the build directory + IFolder folder = project.getFolder(dirName); + if (!folder.exists()) { + // Make sure that parent folders exist + IPath parentPath = (new Path(dirName)).removeLastSegments(1); + // Assume that the parent exists if the path is empty + if (!parentPath.isEmpty()) { + IFolder parent = project.getFolder(parentPath); + if (!parent.exists()) { + createDirectory(parentPath.toString()); + } + } + + // Now make the requested folder + try { + folder.create(true, true, null); + } + catch (CoreException e) { + if (e.getStatus().getCode() == IResourceStatus.PATH_OCCUPIED) + folder.refreshLocal(IResource.DEPTH_ZERO, null); + else + throw e; + } + + // Make sure the folder is marked as derived so it is not added to CM + if (!folder.isDerived()) { + folder.setDerived(true); + } + } + + return folder.getFullPath(); + } + + /* (non-Javadoc) + * Return or create the makefile needed for the build. If we are creating + * the resource, set the derived bit to true so the CM system ignores + * the contents. If the resource exists, respect the existing derived + * setting. + * + * @param makefilePath + * @return IFile + */ + private IFile createFile(IPath makefilePath) throws CoreException { + // Create or get the handle for the makefile + IWorkspaceRoot root = CCorePlugin.getWorkspace().getRoot(); + IFile newFile = root.getFileForLocation(makefilePath); + if (newFile == null) { + newFile = root.getFile(makefilePath); + } + // Create the file if it does not exist + ByteArrayInputStream contents = new ByteArrayInputStream(new byte[0]); + try { + newFile.create(contents, false, new SubProgressMonitor(monitor, 1)); + // Make sure the new file is marked as derived + if (!newFile.isDerived()) { + newFile.setDerived(true); + } + + } + 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; + } + + return newFile; + } + + /** + * @param deletedFile + */ + private void deleteBuildTarget(IResource deletedFile) { + // Get the project relative path of the file + String fileName = getFileName(deletedFile); + String srcExtension = deletedFile.getFileExtension(); + String targetExtension = info.getOutputExtension(srcExtension); + if (targetExtension != "") //$NON-NLS-1$ + fileName += DOT + targetExtension; + IPath projectRelativePath = deletedFile.getProjectRelativePath().removeLastSegments(1); + IPath targetFilePath = getBuildWorkingDir().append(projectRelativePath).append(fileName); + IResource depFile = project.findMember(targetFilePath); + if (depFile != null && depFile.exists()) { + try { + depFile.delete(true, new SubProgressMonitor(monitor, 1)); + } catch (CoreException e) { + // This had better be allowed during a build + + } + } + } + + /** + * @param deletedFile + */ + private void deleteDepFile(IResource deletedFile) { + // Get the project relative path of the file + String fileName = getFileName(deletedFile); + fileName += DOT + DEP_EXT; + IPath projectRelativePath = deletedFile.getProjectRelativePath().removeLastSegments(1); + IPath depFilePath = getBuildWorkingDir().append(projectRelativePath).append(fileName); + IResource depFile = project.findMember(depFilePath); + if (depFile != null && depFile.exists()) { + try { + depFile.delete(true, new SubProgressMonitor(monitor, 1)); + } catch (CoreException e) { + // This had better be allowed during a build + + } + } + } + + /** + * @return Returns the deletedDirList. + */ + private Vector getDeletedDirList() { + if (deletedDirList == null) { + deletedDirList = new Vector(); + } + return deletedDirList; + } + + /* (non-Javadoc) + * @return + */ + private Vector getDeletedFileList() { + if (deletedFileList == null) { + deletedFileList = new Vector(); + } + return deletedFileList; + } + + /* (non-Javadoc) + * @return + */ + private Vector getDependencyMakefiles() { + if (dependencyMakefiles == null) { + dependencyMakefiles = new Vector(); + } + return dependencyMakefiles; + } + + /* (non-Javadoc) + * Strips off the file extension from the argument and returns + * the name component in a String + * + * @param file + * @return + */ + private String getFileName(IResource file) { + String answer = new String(); + String lastSegment = file.getName(); + int extensionSeparator = lastSegment.lastIndexOf(DOT); + if (extensionSeparator != -1) { + answer = lastSegment.substring(0, extensionSeparator); + } + return answer; + } + + /* (non-Javadoc) + * Answers a Vector containing a list of directories that are invalid for the + * build for some reason. At the moment, the only reason a directory would + * not be considered for the build is if it contains a space in the relative + * path from the project root. + * + * @return a a list of directories that are invalid for the build + */ + private Vector getInvalidDirList() { + if (invalidDirList == null) { + invalidDirList = new Vector(); + } + return invalidDirList; + } + + /* (non-javadoc) + * + * @return Vector + */ + private Vector getModifiedList() { + if (modifiedList == null) { + modifiedList = new Vector(); + } + return modifiedList; + } + + /* (non-javadoc) + * Answers the list of subdirectories contributing source code to the build + * + * @return List + */ + private Vector getSubdirList() { + if (subdirList == null) { + subdirList = new Vector(); + } + return subdirList; } /* (non-Javadoc) diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/IManagedBuildGnuToolInfo.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/IManagedBuildGnuToolInfo.java new file mode 100644 index 00000000000..d374d459d8b --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/IManagedBuildGnuToolInfo.java @@ -0,0 +1,106 @@ +/********************************************************************** + * Copyright (c) 2005 Intel Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Intel Corporation - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.managedbuilder.makegen.gnu; + +import java.util.Vector; +import java.util.HashMap; + +/** + * This interface returns information about a Tool's inputs + * and outputs while a Gnu makefile is being generated. + */ +public interface IManagedBuildGnuToolInfo { + public final String DOT = "."; //$NON-NLS-1$ + + /** + * Returns true if the tool's inputs have been calculated, + * else false. + * + * @return boolean + */ + public boolean areInputsCalculated(); + + /** + * Returns the tool's inputs in command line format. This will use + * variables rather than actual file names as appropriate. + * + * @return Vector + */ + public Vector getCommandInputs(); + + /** + * Returns the raw list of tool's input file names. + * + * @return Vector + */ + public Vector getEnumeratedInputs(); + + /** + * Returns true if the tool's outputs have been calculated, + * else false. + * + * @return boolean + */ + public boolean areOutputsCalculated(); + + /** + * Returns the tool's outputs in command line format. This will use + * variables rather than actual file names as appropriate. + * + * @return Vector + */ + public Vector getCommandOutputs(); + + /** + * Returns the raw list of tool's output file names. + * + * @return Vector + */ + public Vector getEnumeratedOutputs(); + + /** + * Returns the raw list of tool's output variable names. + * + * @return Vector + */ + public Vector getOutputVariables(); + + /** + * Returns true if the tool's dependencies have been calculated, + * else false. + * + * @return boolean + */ + public boolean areDependenciesCalculated(); + + /** + * Returns the tool's dependencies in command line format. This will use + * variables rather than actual file names as appropriate. + * + * @return Vector + */ + public Vector getCommandDependencies(); + + /** + * Returns the raw list of tool's input dependencies. + * + * @return Vector + */ + //public Vector getEnumeratedDependencies(); + + /** + * Returns true if this is the target tool + * else false. + * + * @return boolean + */ + public boolean isTargetTool(); +} diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/ManagedBuildGnuToolInfo.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/ManagedBuildGnuToolInfo.java new file mode 100644 index 00000000000..eb5de96fcde --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/ManagedBuildGnuToolInfo.java @@ -0,0 +1,681 @@ +/********************************************************************** + * Copyright (c) 2005 Intel Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Intel Corporation - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.managedbuilder.makegen.gnu; + +import java.util.Iterator; +import java.util.List; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Vector; +import java.util.Map; +import java.util.HashMap; +import java.util.HashSet; + +import org.eclipse.cdt.managedbuilder.core.IAdditionalInput; +import org.eclipse.cdt.managedbuilder.core.IInputType; +import org.eclipse.cdt.managedbuilder.core.IOutputType; +import org.eclipse.cdt.managedbuilder.core.ITool; +import org.eclipse.cdt.managedbuilder.core.IOption; +import org.eclipse.cdt.managedbuilder.core.IManagedOutputNameProvider; +import org.eclipse.cdt.managedbuilder.core.BuildException; +import org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator; +import org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyGenerator; +import org.eclipse.cdt.managedbuilder.internal.core.ManagedMakeMessages; +import org.eclipse.cdt.managedbuilder.internal.core.Tool; +import org.eclipse.cdt.managedbuilder.makegen.gnu.GnuMakefileGenerator; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; + +/** + * This class represents information about a Tool's inputs + * and outputs while a Gnu makefile is being generated. + */ +public class ManagedBuildGnuToolInfo implements IManagedBuildGnuToolInfo { + + private static final String EMPTY_STRING = new String(); + private static final String OBJS_MACRO = "OBJS"; //$NON-NLS-1$ + private static final String DEPS_MACRO = "DEPS"; //$NON-NLS-1$ + + /* + * Members + */ + private IProject project; + private Tool tool; + private boolean bIsTargetTool; + private String targetName; + private String targetExt; + private boolean inputsCalculated = false; + private boolean outputsCalculated = false; + private boolean outputVariablesCalculated = false; + private boolean dependenciesCalculated = false; + private Vector commandInputs = new Vector(); + private Vector enumeratedInputs = new Vector(); + private Vector commandOutputs = new Vector(); + private Vector enumeratedOutputs = new Vector(); + private Vector outputVariables = new Vector(); + private Vector commandDependencies = new Vector(); + //private Vector enumeratedDependencies = new Vector(); + // Map of macro names (String) to values (List) + + /* + * Constructor + */ + public ManagedBuildGnuToolInfo(IProject project, ITool tool, boolean targetTool, String name, String ext) { + this.project = project; + this.tool = (Tool)tool; + bIsTargetTool = targetTool; + if (bIsTargetTool) { + targetName = name; + targetExt = ext; + } + } + + /* + * IManagedBuildGnuToolInfo Methods + */ + public boolean areInputsCalculated() { + return inputsCalculated; + } + + public Vector getCommandInputs() { + return commandInputs; + } + + public Vector getEnumeratedInputs() { + return enumeratedInputs; + } + + public boolean areOutputsCalculated() { + return outputsCalculated; + } + + public Vector getCommandOutputs() { + return commandOutputs; + } + + public Vector getEnumeratedOutputs() { + return enumeratedOutputs; + } + + public Vector getOutputVariables() { + return outputVariables; + } + + public boolean areOutputVariablesCalculated() { + return outputVariablesCalculated; + } + + public boolean areDependenciesCalculated() { + return dependenciesCalculated; + } + + public Vector getCommandDependencies() { + return commandDependencies; + } + + //public Vector getEnumeratedDependencies() { + // return enumeratedDependencies; + //} + + public boolean isTargetTool() { + return bIsTargetTool; + } + + /* + * Other Methods + */ + + public boolean calculateInputs(GnuMakefileGenerator makeGen, IResource[] projResources, boolean lastChance) { + // Get the inputs for this tool invocation + // Note that command inputs that are also dependencies are also added to the command dependencies list + boolean done = true; + Vector myCommandInputs = new Vector(); + Vector myCommandDependencies = new Vector(); + Vector myEnumeratedInputs = new Vector(); + + IInputType[] inTypes = tool.getInputTypes(); + if (inTypes != null && inTypes.length > 0) { + for (int i=0; i 0) { + String cmdVariable = variable = "$(" + variable + ")"; //$NON-NLS-1$ //$NON-NLS-2$ + myCommandInputs.add(cmdVariable); + myCommandDependencies.add(cmdVariable); + // If there is an output variable with the same name, get + // the files associated with it. + List outMacroList = makeGen.getBuildVariableList(variable, true); + if (outMacroList != null) { + myEnumeratedInputs.addAll(outMacroList); + } else { + // If "last chance", then calculate using file extensions below + if (lastChance) { + useFileExts = true; + } else { + done = false; + break; + } + } + } + if (variable.length() == 0 || useFileExts) { + if (type.getMultipleOfType()) { + // Calculate myEnumeratedInputs using the file extensions and the resources in the project + String[] exts = tool.getAllInputExtensions(); + if (projResources != null) { + for (int j=0; j.: $(OBJS) + myCommandInputs.add("$(OBJS)"); //$NON-NLS-1$ + myCommandInputs.add("$(USER_OBJS)"); //$NON-NLS-1$ + myCommandInputs.add("$(LIBS)"); //$NON-NLS-1$ + } else { + // Rule will be generated by addRuleForSource + } + } + + if (done) { + commandInputs.addAll(myCommandInputs); + commandDependencies.addAll(myCommandDependencies); + enumeratedInputs.addAll(myEnumeratedInputs); + inputsCalculated = true; + return true; + } + + return false; + } + + /* + * The priorities for determining the names of the ouputs of a tool are: + * 1. If the tool is the build target and primary output, use artifact name & extension + * 2. If an option is specified, use the value of the option + * 3. If a nameProvider is specified, call it + * 4. If outputNames is specified, use it + * 5. Use the name pattern to generate a transformation macro + * so that the source names can be transformed into the target names + * using the built-in string substitution functions of make. + */ + public boolean calculateOutputs(GnuMakefileGenerator makeGen, HashSet handledInputExtensions, boolean lastChance) { + + boolean done = true; + Vector myCommandOutputs = new Vector(); + Vector myEnumeratedOutputs = new Vector(); + HashMap myOutputMacros = new HashMap(); + // The next two fields are used together + Vector myBuildVars = new Vector(); + Vector myBuildVarsValues = new Vector(); + + // Get the outputs for this tool invocation + IOutputType[] outTypes = tool.getOutputTypes(); + if (outTypes != null && outTypes.length > 0) { + for (int i=0; i 0) { + outputName += (DOT + targetExt); + } + myCommandOutputs.add(outputName); + typeEnumeratedOutputs.add(outputName); + // But this doesn't use any output macro... + } else + // 2. If an option is specified, use the value of the option + if (option != null) { + try { + List outputs = new ArrayList(); + int optType = option.getValueType(); + if (optType == IOption.STRING) { + outputs.add(outputPrefix + option.getStringValue()); + } else if ( + optType == IOption.STRING_LIST || + optType == IOption.LIBRARIES || + optType == IOption.OBJECTS) { + outputs = (List)option.getValue(); + // Add outputPrefix to each if necessary + if (outputPrefix.length() > 0) { + for (int j=0; j 0) { + if (myOutputMacros.containsKey(variable)) { + List currList = (List)myOutputMacros.get(variable); + currList.addAll(outputs); + myOutputMacros.put(variable, currList); + } else { + myOutputMacros.put(variable, outputs); + } + } + } catch( BuildException ex ) { + } + } else + // 3. If a nameProvider is specified, call it + if (nameProvider != null) { + // The inputs must have been calculated before we can do this + IPath[] outNames = null; + if (!inputsCalculated) { + done = false; + } else { + Vector inputs = getEnumeratedInputs(); + IPath[] inputPaths = new IPath[inputs.size()]; + for (int j=0; j 0 && outNames != null) { + if (myOutputMacros.containsKey(variable)) { + List currList = (List)myOutputMacros.get(variable); + currList.addAll(Arrays.asList(outNames)); + myOutputMacros.put(variable, currList); + } else { + myOutputMacros.put(variable, Arrays.asList(outNames)); + } + } + } else + // 4. If outputNames is specified, use it + if (outputNames != null) { + String[] pathTokens = outputNames.split(";"); //$NON-NLS-1$ + if (pathTokens.length > 0) { + List namesList = Arrays.asList(pathTokens); + myCommandOutputs.addAll(namesList); + typeEnumeratedOutputs.addAll(namesList); + if (variable.length() > 0) { + if (myOutputMacros.containsKey(variable)) { + List currList = (List)myOutputMacros.get(variable); + currList.addAll(namesList); + myOutputMacros.put(variable, currList); + } else { + myOutputMacros.put(variable, namesList); + } + } + } + } else { + // 5. Use the name pattern to generate a transformation macro + // so that the source names can be transformed into the target names + // using the built-in string substitution functions of make. + if (multOfType) { + // This case is not handled - a nameProvider or outputNames must be specified + List errList = new ArrayList(); + errList.add(ManagedMakeMessages.getResourceString("MakefileGenerator.error.no.nameprovider")); //$NON-NLS-1$ + myCommandOutputs.add(errList); + } else { + String namePattern = type.getNamePattern(); + if (namePattern == null || namePattern.length() == 0) { + namePattern = outputPrefix + IManagedBuilderMakefileGenerator.WILDCARD; + } + else if (outputPrefix.length() > 0) { + namePattern = outputPrefix + namePattern; + } + String outExt = (type.getOutputExtensions())[0]; + if (outExt != null && outExt.length() > 0) { + namePattern += DOT + outExt; + } + + // Calculate the output name + // The inputs must have been calculated before we can do this + if (!inputsCalculated) { + done = false; + } else { + Vector inputs = getEnumeratedInputs(); + String fileName; + if (inputs.size() > 0) { + // Get the input file name + fileName = (Path.fromOSString((String)inputs.get(0))).removeFileExtension().lastSegment(); + // Check if this is a build macro. If so, use the raw macro name. + if (fileName.startsWith("$(") && fileName.endsWith(")")) { //$NON-NLS-1$ //$NON-NLS-2$ + fileName = fileName.substring(2,fileName.length()-1); + } + } else { + fileName = "default"; //$NON-NLS-1$ + } + // Replace the % with the file name + myCommandOutputs.add(namePattern.replaceAll("%", fileName)); //$NON-NLS-1$ + typeEnumeratedOutputs.add(namePattern.replaceAll("%", fileName)); //$NON-NLS-1$ + if (variable.length() > 0) { + List outputs = new ArrayList(); + outputs.add(fileName); + if (myOutputMacros.containsKey(variable)) { + List currList = (List)myOutputMacros.get(variable); + currList.addAll(outputs); + myOutputMacros.put(variable, currList); + } else { + myOutputMacros.put(variable, outputs); + } + } + } + } + } + if (variable.length() > 0) { + myBuildVars.add(variable); + myBuildVarsValues.add(typeEnumeratedOutputs); + } + myEnumeratedOutputs.addAll(typeEnumeratedOutputs); + } + } else { + if (bIsTargetTool) { + String outputPrefix = tool.getOutputPrefix(); + String outputName = outputPrefix + targetName; + if (targetExt.length() > 0) { + outputName += (DOT + targetExt); + } + myCommandOutputs.add(outputName); + myEnumeratedOutputs.add(outputName); + } else { + // For support of pre-CDT 3.0 integrations. + // NOTE WELL: This only supports the case of a single "target tool" + // that consumes exactly all of the object files, $OBJS, produced + // by other tools in the build and produces a single output + } + } + + // Add the output macros of this tool to the buildOutVars map + Iterator iterator = myOutputMacros.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = (Map.Entry)iterator.next(); + String macroName = (String)entry.getKey(); + List newMacroValue = (List)entry.getValue(); + HashMap map = makeGen.getBuildOutputVars(); + if (map.containsKey(macroName)) { + List macroValue = (List)map.get(macroName); + macroValue.addAll(newMacroValue); + map.put(macroName, macroValue); + } else { + map.put(macroName, newMacroValue); + } + } + outputVariablesCalculated = true; + + if (done) { + commandOutputs.addAll(myCommandOutputs); + enumeratedOutputs.addAll(myEnumeratedOutputs); + outputVariables.addAll(myOutputMacros.keySet()); + outputsCalculated = true; + for (int i=0; i 0) { + for (int i=0; i 0) { + for (int j=0; j.: $(OBJS) + myCommandDependencies.add("$(OBJS)"); //$NON-NLS-1$ + myCommandDependencies.add("$(USER_OBJS)"); //$NON-NLS-1$ + } else { + String[] extensionsList = tool.getAllInputExtensions(); + + // Handle dependencies from the dependencyCalculator + IManagedDependencyGenerator depGen = tool.getDependencyGenerator(); + if (depGen != null) { + int calcType = depGen.getCalculatorType(); + switch (calcType) { + case IManagedDependencyGenerator.TYPE_COMMAND: + // iterate over all extensions that the tool knows how to handle + for (int i=0; i