1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-24 01:15:29 +02:00

Finish and test the new default dependency calculators

This commit is contained in:
Leo Treggiari 2006-02-27 17:53:28 +00:00
parent a622b064ff
commit 315280abca
10 changed files with 1186 additions and 735 deletions

View file

@ -1,494 +1,503 @@
/*******************************************************************************
* 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 Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.core;
import org.eclipse.cdt.managedbuilder.envvar.IConfigurationEnvironmentVariableSupplier;
import org.eclipse.cdt.managedbuilder.macros.IConfigurationBuildMacroSupplier;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
/**
* A tool-integrator defines default configurations as children of the project type.
* These provide a template for the configurations added to the user's project,
* which are stored in the project's .cdtbuild file.
* <p>
* The configuration contains one child of type tool-chain. This describes how the
* project's resources are transformed into the build artifact. The configuration can
* contain one or more children of type resourceConfiguration. These describe build
* settings of individual resources that are different from the configuration as a whole.
*
* @since 2.1
*/
public interface IConfiguration extends IBuildObject {
public static final String ARTIFACT_NAME = "artifactName"; //$NON-NLS-1$
public static final String CLEAN_COMMAND = "cleanCommand"; //$NON-NLS-1$
public static final String PREBUILD_STEP = "prebuildStep"; //$NON-NLS-1$
public static final String POSTBUILD_STEP = "postbuildStep"; //$NON-NLS-1$
public static final String PREANNOUNCEBUILD_STEP = "preannouncebuildStep"; //$NON-NLS-1$
public static final String POSTANNOUNCEBUILD_STEP = "postannouncebuildStep"; //$NON-NLS-1$
// Schema element names
public static final String CONFIGURATION_ELEMENT_NAME = "configuration"; //$NON-NLS-1$
public static final String ERROR_PARSERS = "errorParsers"; //$NON-NLS-1$
public static final String EXTENSION = "artifactExtension"; //$NON-NLS-1$
public static final String PARENT = "parent"; //$NON-NLS-1$
public static final String DESCRIPTION = "description"; //$NON-NLS-1$
/**
* Returns the description of the configuration.
*
* @return String
*/
public String getDescription();
/**
* Sets the description of the receiver to the value specified in the argument
*
* @param description
*/
public void setDescription(String description);
/**
* Creates a child resource configuration corresponding to the passed in file.
*
* @param file
* @return IResourceConfiguration
*/
public IResourceConfiguration createResourceConfiguration(IFile file);
/**
* Creates the <code>IToolChain</code> child of this configuration.
*
* @param ToolChain The superClass, if any
* @param String The id for the new tool chain
* @param String The name for the new tool chain
*
* @return IToolChain
*/
public IToolChain createToolChain(IToolChain superClass, String Id, String name, boolean isExtensionElement);
/**
* Returns the extension that should be applied to build artifacts created by
* this configuration.
*
* @return String
*/
public String getArtifactExtension();
/**
* Returns the name of the final build artifact.
*
* @return String
*/
public String getArtifactName();
/**
* Returns the build arguments from this configuration's builder
*
* @return String
*/
public String getBuildArguments();
/**
* Returns the build command from this configuration's builder
*
* @return String
*/
public String getBuildCommand();
/**
* Returns the prebuild step command
*
* @return String
*/
public String getPrebuildStep();
/**
* Returns the postbuild step command
*
* @return String
*/
public String getPostbuildStep();
/**
* Returns the display string associated with the prebuild step
*
* @return String
*/
public String getPreannouncebuildStep();
/**
* Returns the display string associated with the postbuild step
*
* @return String
*/
public String getPostannouncebuildStep();
/**
* Answers the OS-specific command to remove files created by the build
* of this configuration.
*
* @return String
*/
public String getCleanCommand();
/**
* Answers the semicolon separated list of unique IDs of the error parsers associated
* with this configuration.
*
* @return String
*/
public String getErrorParserIds();
/**
* Answers the ordered list of unique IDs of the error parsers associated
* with this configuration.
*
* @return String[]
*/
public String[] getErrorParserList();
/**
* Projects have C or CC natures. Tools can specify a filter so they are not
* misapplied to a project. This method allows the caller to retrieve a list
* of tools from a project that are correct for a project's nature.
*
* @return an array of <code>ITools</code> that have compatible filters
* for this configuration.
*/
ITool[] getFilteredTools();
/**
* Returns the managed-project parent of this configuration, if this is a
* project configuration. Otherwise, returns <code>null</code>.
*
* @return IManagedProject
*/
public IManagedProject getManagedProject();
/**
* Returns the Eclipse project that owns the configuration.
*
* @return IResource
*/
public IResource getOwner();
/**
* Returns the configuration that this configuration is based on.
*
* @return IConfiguration
*/
public IConfiguration getParent();
/**
* Returns the project-type parent of this configuration, if this is an
* extension configuration. Otherwise, returns <code>null</code>.
*
* @return IProjectType
*/
public IProjectType getProjectType();
/**
* Returns the resource configuration child of this configuration
* that is associated with the project resource, or <code>null</code> if none.
*
* @return IResourceConfiguration
*/
public IResourceConfiguration getResourceConfiguration(String path);
/**
* Returns the resource configuration children of this configuration.
*
* @return IResourceConfigurations[]
*/
public IResourceConfiguration[] getResourceConfigurations();
/**
* Returns the <code>ITool</code> in this configuration's tool-chain with
* the same id as the argument, or <code>null</code>.
*
* @param id unique identifier to search for
* @return ITool
*/
public ITool getTool(String id);
/**
* Returns the <code>ITool</code> in this configuration's tool-chain with
* the specified ID, or the tool(s) with a superclass with this id.
*
* <p>If the tool-chain does not have a tool with that ID, the method
* returns an empty array. It is the responsibility of the caller to
* verify the return value.
*
* @param id unique identifier of the tool to search for
* @return <code>ITool[]</code>
* @since 3.0.2
*/
public ITool[] getToolsBySuperClassId(String id);
/**
* Returns the <code>IToolChain</code> child of this configuration.
*
* @return IToolChain
*/
public IToolChain getToolChain();
/**
* Returns the command-line invocation command for the specified tool.
*
* @param tool The tool that will have its command retrieved.
* @return String The command
*/
public String getToolCommand(ITool tool);
/**
* Returns the tools that are used in this configuration's tool-chain.
*
* @return ITool[]
*/
public ITool[] getTools();
/**
* Returns the tool in this configuration that creates the build artifact.
*
* @return ITool
*/
public ITool getTargetTool();
/**
* Returns <code>true</code> if this configuration has overridden the default build
* build command in this configuration, otherwise <code>false</code>.
*
* @return boolean
*/
public boolean hasOverriddenBuildCommand();
/**
* Returns <code>true</code> if this configuration has changes that need to
* be saved in the project file, else <code>false</code>.
* Should not be called for an extension configuration.
*
* @return boolean
*/
public boolean isDirty();
/**
* Returns <code>true</code> if this configuration was loaded from a manifest file,
* and <code>false</code> if it was loaded from a project (.cdtbuild) file.
*
* @return boolean
*/
public boolean isExtensionElement();
/**
* Returns whether this configuration has been changed and requires the
* project to be rebuilt.
*
* @return <code>true</code> if the configuration contains a change
* that needs the project to be rebuilt.
* Should not be called for an extension configuration.
*/
public boolean needsRebuild();
/**
* Removes a resource configuration from the configuration's list.
*
* @param option
*/
public void removeResourceConfiguration(IResourceConfiguration resConfig);
/**
* Set (override) the extension that should be appended to the build artifact
* for the receiver.
*
* @param extension
*/
public void setArtifactExtension(String extension);
/**
* Set the name of the artifact that will be produced when the receiver
* is built.
*
* @param name
*/
public void setArtifactName(String name);
/**
* Sets the arguments to be passed to the build utility used by the
* receiver to produce a build goal.
*
* @param makeArgs
*/
public void setBuildArguments(String makeArgs);
/**
* Sets the build command for the receiver to the value in the argument.
*
* @param command
*/
public void setBuildCommand(String command);
/**
* Sets the prebuild step for the receiver to the value in the argument.
*
* @param step
*/
public void setPrebuildStep(String step);
/**
* Sets the postbuild step for the receiver to the value in the argument.
*
* @param step
*/
public void setPostbuildStep(String step);
/**
* Sets the prebuild step display string for the receiver to the value in the argument.
*
* @param announceStep
*/
public void setPreannouncebuildStep(String announceStep);
/**
* Sets the postbuild step display string for the receiver to the value in the argument.
*
* @param announceStep
*/
public void setPostannouncebuildStep(String announceStep);
/**
* Sets the command used to clean the outputs of this configuration.
*
* @param name
*/
public void setCleanCommand(String command);
/**
* Sets the element's "dirty" (have I been modified?) flag.
*
* @param isDirty
*/
public void setDirty(boolean isDirty);
/**
* Sets the semicolon separated list of error parser ids
*
* @param ids
*/
public void setErrorParserIds(String ids);
/**
* Sets the name of the receiver to the value specified in the argument
*
* @param name
*/
public void setName(String name);
/**
* Sets the value of a boolean option for this configuration.
*
* @param parent The holder/parent of the option.
* @param option The option to change.
* @param value The value to apply to the option.
*
* @return IOption The modified option. This can be the same option or a newly created option.
*
* @throws BuildException
*
* @since 3.0 - The type of parent has changed from ITool to IHoldsOptions.
* Code assuming ITool as type, will continue to work unchanged.
*/
public IOption setOption(IHoldsOptions parent, IOption option, boolean value)
throws BuildException;
/**
* Sets the value of a string option for this configuration.
*
* @param parent The holder/parent of the option.
* @param option The option that will be effected by change.
* @param value The value to apply to the option.
*
* @return IOption The modified option. This can be the same option or a newly created option.
*
* @throws BuildException
*
* @since 3.0 - The type of parent has changed from ITool to IHoldsOptions.
* Code assuming ITool as type, will continue to work unchanged.
*/
public IOption setOption(IHoldsOptions parent, IOption option, String value)
throws BuildException;
/**
* Sets the value of a list option for this configuration.
*
* @param parent The holder/parent of the option.
* @param option The option to change.
* @param value The values to apply to the option.
*
* @return IOption The modified option. This can be the same option or a newly created option.
*
* @throws BuildException
*
* @since 3.0 - The type of parent has changed from ITool to IHoldsOptions.
* Code assuming ITool as type, will continue to work unchanged.
*/
public IOption setOption(IHoldsOptions parent, IOption option, String[] value)
throws BuildException;
/**
* Sets the rebuild state in this configuration.
*
* @param rebuild <code>true</code> will force a rebuild the next time the project builds
* @see org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo#setRebuildState(boolean)
*/
void setRebuildState(boolean rebuild);
/**
* Overrides the tool command for a tool defined in this configuration's tool-chain.
*
* @param tool The tool that will have its command modified.
* @param command The command
*/
public void setToolCommand(ITool tool, String command);
/**
* Returns <code>true</code> if the configuration's tool-chain is supported on the system
* otherwise returns <code>false</code>
*
* @return boolean
*/
public boolean isSupported();
/**
* Returns the implementation of the IConfigurationEnvironmentVariableSupplier provided
* by the tool-integrator or <code>null</code> if none.
*
* @return IConfigurationEnvironmentVariableSupplier
*/
public IConfigurationEnvironmentVariableSupplier getEnvironmentVariableSupplier();
/**
* Returns the tool-integrator provided implementation of the configuration build macro supplier
* or <code>null</code> if none.
*
* @return IConfigurationBuildMacroSupplier
*/
public IConfigurationBuildMacroSupplier getBuildMacroSupplier();
/**
* answers true if the configuration is temporary, otherwise - false
* @return boolean
*/
public boolean isTemporary();
}
/*******************************************************************************
* 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 Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.core;
import org.eclipse.cdt.managedbuilder.envvar.IConfigurationEnvironmentVariableSupplier;
import org.eclipse.cdt.managedbuilder.macros.IConfigurationBuildMacroSupplier;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
/**
* A tool-integrator defines default configurations as children of the project type.
* These provide a template for the configurations added to the user's project,
* which are stored in the project's .cdtbuild file.
* <p>
* The configuration contains one child of type tool-chain. This describes how the
* project's resources are transformed into the build artifact. The configuration can
* contain one or more children of type resourceConfiguration. These describe build
* settings of individual resources that are different from the configuration as a whole.
*
* @since 2.1
*/
public interface IConfiguration extends IBuildObject {
public static final String ARTIFACT_NAME = "artifactName"; //$NON-NLS-1$
public static final String CLEAN_COMMAND = "cleanCommand"; //$NON-NLS-1$
public static final String PREBUILD_STEP = "prebuildStep"; //$NON-NLS-1$
public static final String POSTBUILD_STEP = "postbuildStep"; //$NON-NLS-1$
public static final String PREANNOUNCEBUILD_STEP = "preannouncebuildStep"; //$NON-NLS-1$
public static final String POSTANNOUNCEBUILD_STEP = "postannouncebuildStep"; //$NON-NLS-1$
// Schema element names
public static final String CONFIGURATION_ELEMENT_NAME = "configuration"; //$NON-NLS-1$
public static final String ERROR_PARSERS = "errorParsers"; //$NON-NLS-1$
public static final String EXTENSION = "artifactExtension"; //$NON-NLS-1$
public static final String PARENT = "parent"; //$NON-NLS-1$
public static final String DESCRIPTION = "description"; //$NON-NLS-1$
/**
* Returns the description of the configuration.
*
* @return String
*/
public String getDescription();
/**
* Sets the description of the receiver to the value specified in the argument
*
* @param description
*/
public void setDescription(String description);
/**
* Creates a child resource configuration corresponding to the passed in file.
*
* @param file
* @return IResourceConfiguration
*/
public IResourceConfiguration createResourceConfiguration(IFile file);
/**
* Creates the <code>IToolChain</code> child of this configuration.
*
* @param ToolChain The superClass, if any
* @param String The id for the new tool chain
* @param String The name for the new tool chain
*
* @return IToolChain
*/
public IToolChain createToolChain(IToolChain superClass, String Id, String name, boolean isExtensionElement);
/**
* Returns the extension that should be applied to build artifacts created by
* this configuration.
*
* @return String
*/
public String getArtifactExtension();
/**
* Returns the name of the final build artifact.
*
* @return String
*/
public String getArtifactName();
/**
* Returns the build arguments from this configuration's builder
*
* @return String
*/
public String getBuildArguments();
/**
* Returns the build command from this configuration's builder
*
* @return String
*/
public String getBuildCommand();
/**
* Returns the prebuild step command
*
* @return String
*/
public String getPrebuildStep();
/**
* Returns the postbuild step command
*
* @return String
*/
public String getPostbuildStep();
/**
* Returns the display string associated with the prebuild step
*
* @return String
*/
public String getPreannouncebuildStep();
/**
* Returns the display string associated with the postbuild step
*
* @return String
*/
public String getPostannouncebuildStep();
/**
* Answers the OS-specific command to remove files created by the build
* of this configuration.
*
* @return String
*/
public String getCleanCommand();
/**
* Answers the semicolon separated list of unique IDs of the error parsers associated
* with this configuration.
*
* @return String
*/
public String getErrorParserIds();
/**
* Answers the ordered list of unique IDs of the error parsers associated
* with this configuration.
*
* @return String[]
*/
public String[] getErrorParserList();
/**
* Projects have C or CC natures. Tools can specify a filter so they are not
* misapplied to a project. This method allows the caller to retrieve a list
* of tools from a project that are correct for a project's nature.
*
* @return an array of <code>ITools</code> that have compatible filters
* for this configuration.
*/
ITool[] getFilteredTools();
/**
* Returns the managed-project parent of this configuration, if this is a
* project configuration. Otherwise, returns <code>null</code>.
*
* @return IManagedProject
*/
public IManagedProject getManagedProject();
/**
* Returns the Eclipse project that owns the configuration.
*
* @return IResource
*/
public IResource getOwner();
/**
* Returns the configuration that this configuration is based on.
*
* @return IConfiguration
*/
public IConfiguration getParent();
/**
* Returns the project-type parent of this configuration, if this is an
* extension configuration. Otherwise, returns <code>null</code>.
*
* @return IProjectType
*/
public IProjectType getProjectType();
/**
* Returns the resource configuration child of this configuration
* that is associated with the project resource, or <code>null</code> if none.
*
* @return IResourceConfiguration
*/
public IResourceConfiguration getResourceConfiguration(String path);
/**
* Returns the resource configuration children of this configuration.
*
* @return IResourceConfigurations[]
*/
public IResourceConfiguration[] getResourceConfigurations();
/**
* Returns the <code>ITool</code> in this configuration's tool-chain with
* the same id as the argument, or <code>null</code>.
*
* @param id unique identifier to search for
* @return ITool
*/
public ITool getTool(String id);
/**
* Returns the <code>ITool</code> in this configuration's tool-chain with
* the specified ID, or the tool(s) with a superclass with this id.
*
* <p>If the tool-chain does not have a tool with that ID, the method
* returns an empty array. It is the responsibility of the caller to
* verify the return value.
*
* @param id unique identifier of the tool to search for
* @return <code>ITool[]</code>
* @since 3.0.2
*/
public ITool[] getToolsBySuperClassId(String id);
/**
* Returns the <code>IToolChain</code> child of this configuration.
*
* @return IToolChain
*/
public IToolChain getToolChain();
/**
* Returns the command-line invocation command for the specified tool.
*
* @param tool The tool that will have its command retrieved.
* @return String The command
*/
public String getToolCommand(ITool tool);
/**
* Returns the tools that are used in this configuration's tool-chain.
*
* @return ITool[]
*/
public ITool[] getTools();
/**
* Returns the tool in this configuration that creates the build artifact.
*
* @return ITool
*/
public ITool getTargetTool();
/**
* Returns <code>true</code> if this configuration has overridden the default build
* build command in this configuration, otherwise <code>false</code>.
*
* @return boolean
*/
public boolean hasOverriddenBuildCommand();
/**
* Returns <code>true</code> if the extension matches one of the special
* file extensions the tools for the configuration consider to be a header file.
*
* @param ext the file extension of the resource
* @return boolean
*/
public boolean isHeaderFile(String ext);
/**
* Returns <code>true</code> if this configuration has changes that need to
* be saved in the project file, else <code>false</code>.
* Should not be called for an extension configuration.
*
* @return boolean
*/
public boolean isDirty();
/**
* Returns <code>true</code> if this configuration was loaded from a manifest file,
* and <code>false</code> if it was loaded from a project (.cdtbuild) file.
*
* @return boolean
*/
public boolean isExtensionElement();
/**
* Returns whether this configuration has been changed and requires the
* project to be rebuilt.
*
* @return <code>true</code> if the configuration contains a change
* that needs the project to be rebuilt.
* Should not be called for an extension configuration.
*/
public boolean needsRebuild();
/**
* Removes a resource configuration from the configuration's list.
*
* @param option
*/
public void removeResourceConfiguration(IResourceConfiguration resConfig);
/**
* Set (override) the extension that should be appended to the build artifact
* for the receiver.
*
* @param extension
*/
public void setArtifactExtension(String extension);
/**
* Set the name of the artifact that will be produced when the receiver
* is built.
*
* @param name
*/
public void setArtifactName(String name);
/**
* Sets the arguments to be passed to the build utility used by the
* receiver to produce a build goal.
*
* @param makeArgs
*/
public void setBuildArguments(String makeArgs);
/**
* Sets the build command for the receiver to the value in the argument.
*
* @param command
*/
public void setBuildCommand(String command);
/**
* Sets the prebuild step for the receiver to the value in the argument.
*
* @param step
*/
public void setPrebuildStep(String step);
/**
* Sets the postbuild step for the receiver to the value in the argument.
*
* @param step
*/
public void setPostbuildStep(String step);
/**
* Sets the prebuild step display string for the receiver to the value in the argument.
*
* @param announceStep
*/
public void setPreannouncebuildStep(String announceStep);
/**
* Sets the postbuild step display string for the receiver to the value in the argument.
*
* @param announceStep
*/
public void setPostannouncebuildStep(String announceStep);
/**
* Sets the command used to clean the outputs of this configuration.
*
* @param name
*/
public void setCleanCommand(String command);
/**
* Sets the element's "dirty" (have I been modified?) flag.
*
* @param isDirty
*/
public void setDirty(boolean isDirty);
/**
* Sets the semicolon separated list of error parser ids
*
* @param ids
*/
public void setErrorParserIds(String ids);
/**
* Sets the name of the receiver to the value specified in the argument
*
* @param name
*/
public void setName(String name);
/**
* Sets the value of a boolean option for this configuration.
*
* @param parent The holder/parent of the option.
* @param option The option to change.
* @param value The value to apply to the option.
*
* @return IOption The modified option. This can be the same option or a newly created option.
*
* @throws BuildException
*
* @since 3.0 - The type of parent has changed from ITool to IHoldsOptions.
* Code assuming ITool as type, will continue to work unchanged.
*/
public IOption setOption(IHoldsOptions parent, IOption option, boolean value)
throws BuildException;
/**
* Sets the value of a string option for this configuration.
*
* @param parent The holder/parent of the option.
* @param option The option that will be effected by change.
* @param value The value to apply to the option.
*
* @return IOption The modified option. This can be the same option or a newly created option.
*
* @throws BuildException
*
* @since 3.0 - The type of parent has changed from ITool to IHoldsOptions.
* Code assuming ITool as type, will continue to work unchanged.
*/
public IOption setOption(IHoldsOptions parent, IOption option, String value)
throws BuildException;
/**
* Sets the value of a list option for this configuration.
*
* @param parent The holder/parent of the option.
* @param option The option to change.
* @param value The values to apply to the option.
*
* @return IOption The modified option. This can be the same option or a newly created option.
*
* @throws BuildException
*
* @since 3.0 - The type of parent has changed from ITool to IHoldsOptions.
* Code assuming ITool as type, will continue to work unchanged.
*/
public IOption setOption(IHoldsOptions parent, IOption option, String[] value)
throws BuildException;
/**
* Sets the rebuild state in this configuration.
*
* @param rebuild <code>true</code> will force a rebuild the next time the project builds
* @see org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo#setRebuildState(boolean)
*/
void setRebuildState(boolean rebuild);
/**
* Overrides the tool command for a tool defined in this configuration's tool-chain.
*
* @param tool The tool that will have its command modified.
* @param command The command
*/
public void setToolCommand(ITool tool, String command);
/**
* Returns <code>true</code> if the configuration's tool-chain is supported on the system
* otherwise returns <code>false</code>
*
* @return boolean
*/
public boolean isSupported();
/**
* Returns the implementation of the IConfigurationEnvironmentVariableSupplier provided
* by the tool-integrator or <code>null</code> if none.
*
* @return IConfigurationEnvironmentVariableSupplier
*/
public IConfigurationEnvironmentVariableSupplier getEnvironmentVariableSupplier();
/**
* Returns the tool-integrator provided implementation of the configuration build macro supplier
* or <code>null</code> if none.
*
* @return IConfigurationBuildMacroSupplier
*/
public IConfigurationBuildMacroSupplier getBuildMacroSupplier();
/**
* answers true if the configuration is temporary, otherwise - false
* @return boolean
*/
public boolean isTemporary();
}

View file

@ -1213,6 +1213,46 @@ public class Configuration extends BuildObject implements IConfiguration {
return toolChain.isSupported();
return false;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.managedbuilder.core.IConfiguration#isHeaderFile(java.lang.String)
*/
public boolean isHeaderFile(String ext) {
// Check to see if there is a rule to build a file with this extension
IManagedProject manProj = getManagedProject();
IProject project = null;
if (manProj != null) {
project = (IProject)manProj.getOwner();
}
ITool[] tools = getFilteredTools();
for (int index = 0; index < tools.length; index++) {
ITool tool = tools[index];
try {
if (project != null) {
// Make sure the tool is right for the project
switch (tool.getNatureFilter()) {
case ITool.FILTER_C:
if (project.hasNature(CProjectNature.C_NATURE_ID) && !project.hasNature(CCProjectNature.CC_NATURE_ID)) {
return tool.isHeaderFile(ext);
}
break;
case ITool.FILTER_CC:
if (project.hasNature(CCProjectNature.CC_NATURE_ID)) {
return tool.isHeaderFile(ext);
}
break;
case ITool.FILTER_BOTH:
return tool.isHeaderFile(ext);
}
} else {
return tool.isHeaderFile(ext);
}
} catch (CoreException e) {
continue;
}
}
return false;
}
/*
* O B J E C T S T A T E M A I N T E N A N C E

View file

@ -861,34 +861,9 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo {
* @see org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo#isHeaderFile(java.lang.String)
*/
public boolean isHeaderFile(String ext) {
IProject project = (IProject)owner;
// Check to see if there is a rule to build a file with this extension
IConfiguration config = getDefaultConfiguration();
ITool[] tools = config.getFilteredTools();
for (int index = 0; index < tools.length; index++) {
ITool tool = tools[index];
try {
// Make sure the tool is right for the project
switch (tool.getNatureFilter()) {
case ITool.FILTER_C:
if (project.hasNature(CProjectNature.C_NATURE_ID) && !project.hasNature(CCProjectNature.CC_NATURE_ID)) {
return tool.isHeaderFile(ext);
}
break;
case ITool.FILTER_CC:
if (project.hasNature(CCProjectNature.CC_NATURE_ID)) {
return tool.isHeaderFile(ext);
}
break;
case ITool.FILTER_BOTH:
return tool.isHeaderFile(ext);
}
} catch (CoreException e) {
continue;
}
}
return false;
return config.isHeaderFile(ext);
}
/**

View file

@ -16,11 +16,10 @@ import org.eclipse.cdt.managedbuilder.core.ITool;
import org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator;
import org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyGenerator2;
import org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyInfo;
import org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyPreBuild;
import org.eclipse.core.runtime.IPath;
/**
* This dependency calculator uses the GCC -MMD -MF -MP -MQ options in order to
* This dependency calculator uses the GCC -MMD -MF -MP -MT options in order to
* generate .d files as a side effect of compilation.
* See bugzilla 108715 for the discussion of dependency management that led to
* the creation of this dependency calculator. Note also that this technique

View file

@ -23,7 +23,7 @@ import org.eclipse.core.runtime.IPath;
import org.eclipse.core.resources.IProject;;
/**
* This dependency calculator uses the GCC -MMD -MF -MP -MQ options in order to
* This dependency calculator uses the GCC -MMD -MF -MP -MT options in order to
* generate .d files as a side effect of compilation.
* See bugzilla 108715 for the discussion of dependency management that led to
* the creation of this dependency calculator. Note also that this technique

View file

@ -0,0 +1,98 @@
/*******************************************************************************
* Copyright (c) 2006 Intel Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Intel Corporation - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.makegen.gnu;
import java.io.IOException;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.managedbuilder.core.IBuildObject;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.ITool;
import org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator;
import org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyGenerator2;
import org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyInfo;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
/**
* This dependency calculator uses the same dependency management technique as the
* DefaultGCCDependencyCalculator. That is:
*
* 1. An echo command creates the dependency file (.d).
* 2. A second invocation of the compiler is made in order to append to the dependency file.
* The additional options -MM -MG -P -w are added to the command line.
* 3. The dependency files are post-processed to add the empty header rules.
*
* This dependency calculator uses the class DefaultGCCDependencyCalculator3Commands
* which implements the per-source command information
*
* This is an example dependency calculator that is not used by the CDT GCC tool-chain.
*
* @since 3.1
*/
public class DefaultGCCDependencyCalculator3 implements
IManagedDependencyGenerator2 {
/*
* (non-Javadoc)
* @see org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyGeneratorType#getCalculatorType()
*/
public int getCalculatorType() {
return TYPE_BUILD_COMMANDS;
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyGenerator2#getDependencyFileExtension(org.eclipse.cdt.managedbuilder.core.IConfiguration, org.eclipse.cdt.managedbuilder.core.ITool)
*/
public String getDependencyFileExtension(IConfiguration buildContext, ITool tool) {
return IManagedBuilderMakefileGenerator.DEP_EXT;
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyGenerator2#getDependencySourceInfo(org.eclipse.core.runtime.IPath, org.eclipse.cdt.managedbuilder.core.IBuildObject, org.eclipse.cdt.managedbuilder.core.ITool, org.eclipse.core.runtime.IPath)
*/
public IManagedDependencyInfo getDependencySourceInfo(IPath source, IBuildObject buildContext, ITool tool, IPath topBuildDirectory) {
return new DefaultGCCDependencyCalculator3Commands(source, buildContext, tool, topBuildDirectory);
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyGenerator2#postProcessDependencyFile(org.eclipse.core.runtime.IPath, org.eclipse.cdt.managedbuilder.core.IConfiguration, org.eclipse.cdt.managedbuilder.core.ITool, org.eclipse.core.runtime.IPath)
*/
public boolean postProcessDependencyFile(IPath dependencyFile, IConfiguration buildContext, ITool tool, IPath topBuildDirectory) {
try {
IWorkspaceRoot root = CCorePlugin.getWorkspace().getRoot();
IFile makefile;
IPath makefilePath;
if (dependencyFile.isAbsolute()) {
makefilePath = dependencyFile;
} else {
makefilePath = topBuildDirectory.append(dependencyFile);
}
IPath rootPath = root.getLocation();
if (rootPath.isPrefixOf(makefilePath)) {
makefilePath = makefilePath.removeFirstSegments(rootPath.segmentCount());
}
makefile = root.getFile(makefilePath);
return GnuMakefileGenerator.populateDummyTargets(buildContext, makefile, false);
} catch (CoreException e) {
} catch (IOException e) {
}
return false;
}
}

View file

@ -0,0 +1,330 @@
/*******************************************************************************
* Copyright (c) 2006 Intel Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Intel Corporation - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.makegen.gnu;
import org.eclipse.cdt.managedbuilder.core.BuildException;
import org.eclipse.cdt.managedbuilder.core.IBuildObject;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.IManagedCommandLineGenerator;
import org.eclipse.cdt.managedbuilder.core.IManagedCommandLineInfo;
import org.eclipse.cdt.managedbuilder.core.IResourceConfiguration;
import org.eclipse.cdt.managedbuilder.core.ITool;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.cdt.managedbuilder.internal.macros.FileContextData;
import org.eclipse.cdt.managedbuilder.internal.macros.MacroResolver;
import org.eclipse.cdt.managedbuilder.macros.BuildMacroException;
import org.eclipse.cdt.managedbuilder.macros.IBuildMacroProvider;
import org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator;
import org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyCommands;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.resources.IProject;;
/**
* This dependency calculator uses the same dependency management technique as the
* DefaultGCCDependencyCalculator. That is:
*
* 1. An echo command creates the dependency file (.d).
* 2. A second invocation of the compiler is made in order to append to the dependency file.
* The additional options -MM -MG -P -w are added to the command line.
* 3. The dependency files are post-processed to add the empty header rules.
*
* This class is used with DefaultGCCDependencyCalculator3.
*
* This is an example dependency calculator that is not used by the CDT GCC tool-chain.
*
* @since 3.1
*/
public class DefaultGCCDependencyCalculator3Commands implements
IManagedDependencyCommands {
private static final String EMPTY_STRING = new String();
// Member variables set by the constructor
IPath source;
IBuildObject buildContext;
ITool tool;
IPath topBuildDirectory;
// Other Member variables
IProject project;
IConfiguration config;
IResourceConfiguration resConfig;
IPath sourceLocation;
IPath outputLocation;
boolean needExplicitRuleForFile;
boolean genericCommands = true;
/**
* Constructor
*
* @param source The source file for which dependencies should be calculated
* The IPath can be either relative to the project directory, or absolute in the file system.
* @param buildContext The IConfiguration or IResourceConfiguration that
* contains the context in which the source file will be built
* @param tool The tool associated with the source file
* @param topBuildDirectory The top build directory of the configuration. This is
* the working directory for the tool. This IPath is relative to the project directory.
*/
public DefaultGCCDependencyCalculator3Commands(IPath source, IBuildObject buildContext, ITool tool, IPath topBuildDirectory) {
this.source = source;
this.buildContext = buildContext;
this.tool = tool;
this.topBuildDirectory = topBuildDirectory;
// Compute the project
if (buildContext instanceof IConfiguration) {
resConfig = null;
config = (IConfiguration)buildContext;
project = (IProject)config.getOwner();
} else if (buildContext instanceof IResourceConfiguration) {
resConfig = (IResourceConfiguration)buildContext;
config = resConfig.getParent();
project = (IProject)resConfig.getOwner();
}
sourceLocation = (source.isAbsolute() ? source : project.getLocation().append(source));
outputLocation = project.getLocation().append(topBuildDirectory).append(getDependencyFiles()[0]);
// A separate rule is needed for the resource in the case where explicit file-specific macros
// are referenced, or if the resource contains special characters in its path (e.g., whitespace)
needExplicitRuleForFile = GnuMakefileGenerator.containsSpecialCharacters(sourceLocation.toString()) ||
MacroResolver.getReferencedExplitFileMacros(tool).length > 0
|| MacroResolver.getReferencedExplitFileMacros(
tool.getToolCommand(),
IBuildMacroProvider.CONTEXT_FILE,
new FileContextData(sourceLocation, outputLocation,
null, tool)).length > 0;
if (buildContext instanceof IResourceConfiguration || needExplicitRuleForFile)
genericCommands = false;
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyCommands#areCommandsGeneric()
*/
public boolean areCommandsGeneric() {
return genericCommands;
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyCommands#getDependencyCommandOptions()
*/
public String[] getDependencyCommandOptions() {
// Nothing
return null;
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyCommands#getDependencyFiles()
*/
public IPath[] getDependencyFiles() {
// The source file is project relative and the dependency file is top build directory relative
// Remove the source extension and add the dependency extension
IPath depFilePath = source.removeFileExtension().addFileExtension(IManagedBuilderMakefileGenerator.DEP_EXT);
// Remember that the source folder hierarchy and the build output folder hierarchy are the same
// but if this is a generated resource, then it may already be under the top build directory
if (!depFilePath.isAbsolute()) {
if (topBuildDirectory.isPrefixOf(depFilePath)) {
depFilePath = depFilePath.removeFirstSegments(1);
}
}
IPath[] paths = new IPath[1];
paths[0] = depFilePath;
return paths;
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyCommands#getPostToolDependencyCommands()
*/
public String[] getPostToolDependencyCommands() {
/*
* For a given input, <path>/<resource_name>.<ext>, return a string containing
* echo -n $(@:%.<out_ext>=%.d) '<path>/' >> $(@:%.<out_ext>=%.d) && \
* <tool_command> -P -MM -MG <tool_flags> $< >> $(@:%.<out_ext>=%.d)
*
*/
String[] commands = new String[2];
// Get what we need to create the dependency generation command
String inputExtension = source.getFileExtension();
String outputExtension = tool.getOutputExtension(inputExtension);
// Calculate the dependency rule
// <path>/$(@:%.<out_ext>=%.d)
String depRule = "'$(@:%." + //$NON-NLS-1$
outputExtension +
"=%." + //$NON-NLS-1$
IManagedBuilderMakefileGenerator.DEP_EXT +
")'"; //$NON-NLS-1$
// Add the Echo command that will actually create the right format for the dep
commands[0] =
IManagedBuilderMakefileGenerator.TAB +
IManagedBuilderMakefileGenerator.ECHO +
IManagedBuilderMakefileGenerator.WHITESPACE +
"-n" + //$NON-NLS-1$
IManagedBuilderMakefileGenerator.WHITESPACE +
depRule +
IManagedBuilderMakefileGenerator.WHITESPACE +
"$(dir $@)" + //$NON-NLS-1$
IManagedBuilderMakefileGenerator.WHITESPACE +
">" + //$NON-NLS-1$
IManagedBuilderMakefileGenerator.WHITESPACE +
depRule;
// Add the line that will do the work to calculate dependencies
IBuildMacroProvider provider = ManagedBuildManager.getBuildMacroProvider();
IManagedCommandLineInfo cmdLInfo = null;
String buildCmd = null;
String[] inputs= new String[1]; inputs[0] = IManagedBuilderMakefileGenerator.IN_MACRO;
String outputFile = ""; //$NON-NLS-1$
String outflag = ""; //$NON-NLS-1$
String outputPrefix = ""; //$NON-NLS-1$
String cmd = tool.getToolCommand();
//try to resolve the build macros in the tool command
try {
String resolvedCommand = null;
if (!needExplicitRuleForFile) {
resolvedCommand = provider.resolveValueToMakefileFormat(
cmd,
EMPTY_STRING,
IManagedBuilderMakefileGenerator.WHITESPACE,
IBuildMacroProvider.CONTEXT_FILE,
new FileContextData(sourceLocation,
outputLocation, null, tool));
} else {
// if we need an explicit rule then don't use any builder
// variables, resolve everything
// to explicit strings
resolvedCommand = provider.resolveValue(
cmd,
EMPTY_STRING,
IManagedBuilderMakefileGenerator.WHITESPACE,
IBuildMacroProvider.CONTEXT_FILE,
new FileContextData(sourceLocation,
outputLocation, null, tool));
}
if((resolvedCommand = resolvedCommand.trim()).length() > 0)
cmd = resolvedCommand;
} catch (BuildMacroException e){
}
String[] toolFlags = null;
try {
toolFlags = tool.getToolCommandFlags(sourceLocation, outputLocation);
} catch( BuildException ex ) {
toolFlags = new String[0];
}
String[] flags = new String[toolFlags.length + 4];
flags[0] = "-MM"; //$NON-NLS-1$
flags[1] = "-MG"; //$NON-NLS-1$
flags[2] = "-P"; //$NON-NLS-1$
flags[3] = "-w"; //$NON-NLS-1$
for (int i=0; i<toolFlags.length; i++) {
flags[4+i] = toolFlags[i];
}
IManagedCommandLineGenerator cmdLGen = tool.getCommandLineGenerator();
cmdLInfo = cmdLGen.generateCommandLineInfo( tool, cmd, flags, outflag, outputPrefix,
outputFile, inputs, tool.getCommandLinePattern() );
// The command to build
buildCmd = cmdLInfo.getCommandLine();
// resolve any remaining macros in the command after it has been generated
try {
String resolvedCommand = null;
if (!needExplicitRuleForFile) {
resolvedCommand = provider.resolveValueToMakefileFormat(
buildCmd,
EMPTY_STRING,
IManagedBuilderMakefileGenerator.WHITESPACE,
IBuildMacroProvider.CONTEXT_FILE,
new FileContextData(sourceLocation,
outputLocation, null, tool));
} else {
// if we need an explicit rule then don't use any builder
// variables, resolve everything to explicit strings
resolvedCommand = provider.resolveValue(
buildCmd,
EMPTY_STRING,
IManagedBuilderMakefileGenerator.WHITESPACE,
IBuildMacroProvider.CONTEXT_FILE,
new FileContextData(sourceLocation,
outputLocation, null, tool));
}
if((resolvedCommand = resolvedCommand.trim()).length() > 0)
buildCmd = resolvedCommand;
} catch (BuildMacroException e){
}
commands[1] =
IManagedBuilderMakefileGenerator.TAB +
buildCmd +
IManagedBuilderMakefileGenerator.WHITESPACE +
">>" + //$NON-NLS-1$
IManagedBuilderMakefileGenerator.WHITESPACE + depRule;
return commands;
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyCommands#getPreToolDependencyCommands()
*/
public String[] getPreToolDependencyCommands() {
// Nothing
return null;
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyInfo#getBuildContext()
*/
public IBuildObject getBuildContext() {
return buildContext;
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyInfo#getSource()
*/
public IPath getSource() {
return source;
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyInfo#getTool()
*/
public ITool getTool() {
return tool;
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyInfo#getTopBuildDirectory()
*/
public IPath getTopBuildDirectory() {
return topBuildDirectory;
}
}

View file

@ -16,12 +16,11 @@ import org.eclipse.cdt.managedbuilder.core.ITool;
import org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator;
import org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyGenerator2;
import org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyInfo;
import org.eclipse.cdt.managedbuilder.makegen.IManagedDependencyPreBuild;
import org.eclipse.core.runtime.IPath;
/**
* This dependency calculator uses the GCC -MM -MF -MP -MQ options in order to
* This dependency calculator uses the GCC -MM -MF -MP -MT options in order to
* generate .d files as separate step prior to the source compilations.
*
* This dependency calculator uses the class DefaultGCCDependencyCalculatorPreBuildCommands

View file

@ -122,14 +122,14 @@ public class DefaultGCCDependencyCalculatorPreBuildCommands implements IManagedD
String[] commands = new String[1];
String depCmd = EMPTY_STRING;
IBuildMacroProvider provider = ManagedBuildManager.getBuildMacroProvider();
// Get and resolve the command
String cmd = tool.getToolCommand();
try {
String resolvedCommand = null;
if (!needExplicitRuleForFile) {
resolvedCommand = ManagedBuildManager.getBuildMacroProvider()
.resolveValueToMakefileFormat(
resolvedCommand = provider.resolveValueToMakefileFormat(
cmd,
EMPTY_STRING,
IManagedBuilderMakefileGenerator.WHITESPACE,
@ -140,8 +140,7 @@ public class DefaultGCCDependencyCalculatorPreBuildCommands implements IManagedD
// if we need an explicit rule then don't use any builder
// variables, resolve everything
// to explicit strings
resolvedCommand = ManagedBuildManager.getBuildMacroProvider()
.resolveValue(
resolvedCommand = provider.resolveValue(
cmd,
EMPTY_STRING,
IManagedBuilderMakefileGenerator.WHITESPACE,
@ -177,7 +176,7 @@ public class DefaultGCCDependencyCalculatorPreBuildCommands implements IManagedD
options.add(optTxt);
// -MT"object-file-filename"
optTxt = "-MT\""; //$NON-NLS-1$
GnuMakefileGenerator.escapeWhitespaces((outPath.removeFileExtension()).toString());
optTxt += GnuMakefileGenerator.escapeWhitespaces((outPath.removeFileExtension()).toString());
String outExt = tool.getOutputExtension(source.getFileExtension());
if (outExt != null) optTxt += "." + outExt; //$NON-NLS-1$
optTxt += "\""; //$NON-NLS-1$
@ -225,7 +224,6 @@ public class DefaultGCCDependencyCalculatorPreBuildCommands implements IManagedD
// generated
try {
String resolvedCommand;
IBuildMacroProvider provider = ManagedBuildManager.getBuildMacroProvider();
if (!needExplicitRuleForFile) {
resolvedCommand = provider.resolveValueToMakefileFormat(
depCmd,

View file

@ -408,7 +408,7 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator {
}
}
if (callPopulateDummyTargets) {
populateDummyTargets(depFile, force);
populateDummyTargets(config, depFile, force);
}
} catch (CoreException e) {
throw e;
@ -838,192 +838,6 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator {
/*************************************************************************
* 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
************************************************************************/
/**
* This method postprocesses a .d file created by a build.
* It's main job is to add dummy targets for the header files dependencies.
* This prevents make from aborting the build if the header file does not exist.
*
* A secondary job is to work in tandem with the "echo" command that is used
* by some tool-chains in order to get the "targets" part of the dependency rule
* correct.
*
* This method adds a comment to the beginning of the dependency file which it
* checks for to determine if this dependency file has already been updated.
*/
protected void populateDummyTargets(IFile makefile, boolean force) throws CoreException, IOException {
if (makefile == null || !makefile.exists()) return;
// Get the contents of the dependency file
InputStream contentStream = makefile.getContents(false);
Reader in = new InputStreamReader(contentStream);
StringBuffer inBuffer = null;
int chunkSize = contentStream.available();
inBuffer = new StringBuffer(chunkSize);
char[] readBuffer = new char[chunkSize];
int n = in.read(readBuffer);
while (n > 0) {
inBuffer.append(readBuffer);
n = in.read(readBuffer);
}
contentStream.close();
// The rest of this operation is equally expensive, so
// if we are doing an incremental build, only update the
// files that do not have a comment
if (inBuffer == null) return;
String inBufferString = inBuffer.toString();
if (!force && inBufferString.startsWith(COMMENT_SYMBOL)) {
return;
}
// Try to determine if this file already has dummy targets defined.
// If so, we will only add the comment.
String[] bufferLines = inBufferString.split("[\\r\\n]"); //$NON-NLS-1$
for (int i=0; i<bufferLines.length; i++) {
String bufferLine = bufferLines[i];
if (bufferLine.endsWith(":")) {
StringBuffer outBuffer = addDefaultHeader();
outBuffer.append(inBuffer);
Util.save(outBuffer, makefile);
return;
}
}
// Reconstruct the buffer tokens into useful chunks of dependency information
Vector bufferTokens = new Vector(Arrays.asList(inBufferString.split("\\s"))); //$NON-NLS-1$
Vector deps = new Vector(bufferTokens.size());
Iterator tokenIter = bufferTokens.iterator();
while (tokenIter.hasNext()) {
String token = (String)tokenIter.next();
if (token.lastIndexOf("\\") == token.length() - 1 && token.length() > 1) { //$NON-NLS-1$
// This is escaped so keep adding to the token until we find the end
while (tokenIter.hasNext()) {
String nextToken = (String)tokenIter.next();
token += WHITESPACE + nextToken;
if (!nextToken.endsWith("\\")) { //$NON-NLS-1$
break;
}
}
}
deps.add(token);
}
deps.trimToSize();
// Now find the header file dependencies and make dummy targets for them
boolean save = false;
StringBuffer outBuffer = null;
// If we are doing an incremental build, only update the files that do not have a comment
String firstToken;
try {
firstToken = (String) deps.get(0);
} catch (ArrayIndexOutOfBoundsException e) {
// This makes no sense so bail
return;
}
// Put the generated comments in the output buffer
if (!firstToken.startsWith(COMMENT_SYMBOL)) {
outBuffer = addDefaultHeader();
} else {
outBuffer = new StringBuffer();
}
// Some echo implementations misbehave and put the -n and newline in the output
if (firstToken.startsWith("-n")) { //$NON-NLS-1$
// Now let's parse:
// Win32 outputs -n '<path>/<file>.d <path>/'
// POSIX outputs -n <path>/<file>.d <path>/
// Get the dep file name
String secondToken;
try {
secondToken = (String) deps.get(1);
} catch (ArrayIndexOutOfBoundsException e) {
secondToken = new String();
}
if (secondToken.startsWith("'")) { //$NON-NLS-1$
// This is the Win32 implementation of echo (MinGW without MSYS)
outBuffer.append(secondToken.substring(1) + WHITESPACE);
} else {
outBuffer.append(secondToken + WHITESPACE);
}
// The relative path to the build goal comes next
String thirdToken;
try {
thirdToken = (String) deps.get(2);
} catch (ArrayIndexOutOfBoundsException e) {
thirdToken = new String();
}
int lastIndex = thirdToken.lastIndexOf("'"); //$NON-NLS-1$
if (lastIndex != -1) {
if (lastIndex == 0) {
outBuffer.append(WHITESPACE);
} else {
outBuffer.append(thirdToken.substring(0, lastIndex - 1));
}
} else {
outBuffer.append(thirdToken);
}
// Followed by the target output by the compiler plus ':'
// If we see any empty tokens here, assume they are the result of
// a line feed output by "echo" and skip them
String fourthToken;
int nToken = 3;
try {
do {
fourthToken = (String) deps.get(nToken++);
} while (fourthToken.length() == 0);
} catch (ArrayIndexOutOfBoundsException e) {
fourthToken = new String();
}
outBuffer.append(fourthToken + WHITESPACE);
// Followed by the actual dependencies
try {
Iterator iter = deps.listIterator(nToken);
while (iter.hasNext()) {
String nextElement = (String)iter.next();
if (nextElement.endsWith("\\")) { //$NON-NLS-1$
outBuffer.append(nextElement + NEWLINE + WHITESPACE);
} else {
outBuffer.append(nextElement + WHITESPACE);
}
}
} catch (IndexOutOfBoundsException e) {
}
} else {
outBuffer.append(inBuffer);
}
outBuffer.append(NEWLINE);
save = true;
// Dummy targets to add to the makefile
Iterator dummyIter = deps.iterator();
while (dummyIter.hasNext()) {
String dummy = (String)dummyIter.next();
IPath dep = new Path(dummy);
String extension = dep.getFileExtension();
if (info.isHeaderFile(extension)) {
/*
* The formatting here is
* <dummy_target>:
*/
outBuffer.append(dummy + COLON + NEWLINE + NEWLINE);
}
}
// Write them out to the makefile
if (save) {
Util.save(outBuffer, makefile);
}
}
/* (non-javadoc)
* This method generates a "fragment" make file (subdir.mk).
@ -1550,20 +1364,6 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator {
return buffer;
}
/**
* prepend all instanced of '\' or '"' with a backslash
*
* @param string
* @return
*/
public static String escapedEcho(String string) {
String escapedString = string.replaceAll("(['\"\\\\])", "\\\\$1");
return ECHO + WHITESPACE + escapedString + NEWLINE;
}
public static String ECHO_BLANK_LINE = ECHO + WHITESPACE + SINGLE_QUOTE + WHITESPACE + SINGLE_QUOTE + NEWLINE;
/* (non-javadoc)
* Returns the targets rules. The targets make file (top makefile) contains:
@ -3473,6 +3273,209 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator {
}
return outputExtensionsSet;
}
/**
* This method postprocesses a .d file created by a build.
* It's main job is to add dummy targets for the header files dependencies.
* This prevents make from aborting the build if the header file does not exist.
*
* A secondary job is to work in tandem with the "echo" command that is used
* by some tool-chains in order to get the "targets" part of the dependency rule
* correct.
*
* This method adds a comment to the beginning of the dependency file which it
* checks for to determine if this dependency file has already been updated.
*
* @return a <code>true</code> if the dependency file is modified
*/
static public boolean populateDummyTargets(IConfiguration cfg, IFile makefile, boolean force) throws CoreException, IOException {
if (makefile == null || !makefile.exists()) return false;
// Get the contents of the dependency file
InputStream contentStream = makefile.getContents(false);
Reader in = new InputStreamReader(contentStream);
StringBuffer inBuffer = null;
int chunkSize = contentStream.available();
inBuffer = new StringBuffer(chunkSize);
char[] readBuffer = new char[chunkSize];
int n = in.read(readBuffer);
while (n > 0) {
inBuffer.append(readBuffer);
n = in.read(readBuffer);
}
contentStream.close();
// The rest of this operation is equally expensive, so
// if we are doing an incremental build, only update the
// files that do not have a comment
if (inBuffer == null) return false;
String inBufferString = inBuffer.toString();
if (!force && inBufferString.startsWith(COMMENT_SYMBOL)) {
return false;
}
// Try to determine if this file already has dummy targets defined.
// If so, we will only add the comment.
String[] bufferLines = inBufferString.split("[\\r\\n]"); //$NON-NLS-1$
for (int i=0; i<bufferLines.length; i++) {
String bufferLine = bufferLines[i];
if (bufferLine.endsWith(":")) {
StringBuffer outBuffer = addDefaultHeader();
outBuffer.append(inBuffer);
Util.save(outBuffer, makefile);
return true;
}
}
// Reconstruct the buffer tokens into useful chunks of dependency information
Vector bufferTokens = new Vector(Arrays.asList(inBufferString.split("\\s"))); //$NON-NLS-1$
Vector deps = new Vector(bufferTokens.size());
Iterator tokenIter = bufferTokens.iterator();
while (tokenIter.hasNext()) {
String token = (String)tokenIter.next();
if (token.lastIndexOf("\\") == token.length() - 1 && token.length() > 1) { //$NON-NLS-1$
// This is escaped so keep adding to the token until we find the end
while (tokenIter.hasNext()) {
String nextToken = (String)tokenIter.next();
token += WHITESPACE + nextToken;
if (!nextToken.endsWith("\\")) { //$NON-NLS-1$
break;
}
}
}
deps.add(token);
}
deps.trimToSize();
// Now find the header file dependencies and make dummy targets for them
boolean save = false;
StringBuffer outBuffer = null;
// If we are doing an incremental build, only update the files that do not have a comment
String firstToken;
try {
firstToken = (String) deps.get(0);
} catch (ArrayIndexOutOfBoundsException e) {
// This makes no sense so bail
return false;
}
// Put the generated comments in the output buffer
if (!firstToken.startsWith(COMMENT_SYMBOL)) {
outBuffer = addDefaultHeader();
} else {
outBuffer = new StringBuffer();
}
// Some echo implementations misbehave and put the -n and newline in the output
if (firstToken.startsWith("-n")) { //$NON-NLS-1$
// Now let's parse:
// Win32 outputs -n '<path>/<file>.d <path>/'
// POSIX outputs -n <path>/<file>.d <path>/
// Get the dep file name
String secondToken;
try {
secondToken = (String) deps.get(1);
} catch (ArrayIndexOutOfBoundsException e) {
secondToken = new String();
}
if (secondToken.startsWith("'")) { //$NON-NLS-1$
// This is the Win32 implementation of echo (MinGW without MSYS)
outBuffer.append(secondToken.substring(1) + WHITESPACE);
} else {
outBuffer.append(secondToken + WHITESPACE);
}
// The relative path to the build goal comes next
String thirdToken;
try {
thirdToken = (String) deps.get(2);
} catch (ArrayIndexOutOfBoundsException e) {
thirdToken = new String();
}
int lastIndex = thirdToken.lastIndexOf("'"); //$NON-NLS-1$
if (lastIndex != -1) {
if (lastIndex == 0) {
outBuffer.append(WHITESPACE);
} else {
outBuffer.append(thirdToken.substring(0, lastIndex - 1));
}
} else {
outBuffer.append(thirdToken);
}
// Followed by the target output by the compiler plus ':'
// If we see any empty tokens here, assume they are the result of
// a line feed output by "echo" and skip them
String fourthToken;
int nToken = 3;
try {
do {
fourthToken = (String) deps.get(nToken++);
} while (fourthToken.length() == 0);
} catch (ArrayIndexOutOfBoundsException e) {
fourthToken = new String();
}
outBuffer.append(fourthToken + WHITESPACE);
// Followed by the actual dependencies
try {
Iterator iter = deps.listIterator(nToken);
while (iter.hasNext()) {
String nextElement = (String)iter.next();
if (nextElement.endsWith("\\")) { //$NON-NLS-1$
outBuffer.append(nextElement + NEWLINE + WHITESPACE);
} else {
outBuffer.append(nextElement + WHITESPACE);
}
}
} catch (IndexOutOfBoundsException e) {
}
} else {
outBuffer.append(inBuffer);
}
outBuffer.append(NEWLINE);
save = true;
// Dummy targets to add to the makefile
Iterator dummyIter = deps.iterator();
while (dummyIter.hasNext()) {
String dummy = (String)dummyIter.next();
IPath dep = new Path(dummy);
String extension = dep.getFileExtension();
if (cfg.isHeaderFile(extension)) {
/*
* The formatting here is
* <dummy_target>:
*/
outBuffer.append(dummy + COLON + NEWLINE + NEWLINE);
}
}
// Write them out to the makefile
if (save) {
Util.save(outBuffer, makefile);
return true;
}
return false;
}
/**
* prepend all instanced of '\' or '"' with a backslash
*
* @param string
* @return
*/
static public String escapedEcho(String string) {
String escapedString = string.replaceAll("(['\"\\\\])", "\\\\$1");
return ECHO + WHITESPACE + escapedString + NEWLINE;
}
static public String ECHO_BLANK_LINE = ECHO + WHITESPACE + SINGLE_QUOTE + WHITESPACE + SINGLE_QUOTE + NEWLINE;
/* (non-Javadoc)
* Outputs a comment formatted as follows:
@ -3480,7 +3483,7 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator {
* # <Comment message>
* ##### ....... #####
*/
protected StringBuffer addDefaultHeader() {
static protected StringBuffer addDefaultHeader() {
StringBuffer buffer = new StringBuffer();
outputCommentLine(buffer);
buffer.append(COMMENT_SYMBOL + WHITESPACE + ManagedMakeMessages.getResourceString(HEADER) + NEWLINE);
@ -3492,7 +3495,7 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator {
/* (non-Javadoc)
* Put COLS_PER_LINE comment charaters in the argument.
*/
protected void outputCommentLine(StringBuffer buffer) {
static protected void outputCommentLine(StringBuffer buffer) {
for (int i = 0; i < COLS_PER_LINE; i++) {
buffer.append(COMMENT_SYMBOL);
}
@ -3509,7 +3512,7 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator {
*
* @param path
*/
public static String escapeWhitespaces(String path) {
static public 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) {