diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/plugin.xml b/build/org.eclipse.cdt.managedbuilder.core.tests/plugin.xml index 3089dfb884e..dc00361aaa6 100644 --- a/build/org.eclipse.cdt.managedbuilder.core.tests/plugin.xml +++ b/build/org.eclipse.cdt.managedbuilder.core.tests/plugin.xml @@ -6,12 +6,11 @@ version="1.0.0"> - + - 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 833038cf861..3f4974be2c8 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 @@ -46,7 +46,6 @@ import org.eclipse.cdt.managedbuilder.core.IToolReference; import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.cdt.managedbuilder.core.ManagedCProjectNature; import org.eclipse.cdt.managedbuilder.internal.core.OptionReference; -import org.eclipse.cdt.testplugin.FileManager; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; @@ -1435,8 +1434,6 @@ public class ManagedBuildCoreTests extends TestCase { public void testBug43450 () throws Exception{ IProject project = createProject( projectName ); - FileManager fileManager = new FileManager(); - IFolder folder = project.getProject().getFolder( "includes" ); if( !folder.exists() ){ folder.create( false, true, null ); diff --git a/build/org.eclipse.cdt.managedbuilder.core/plugin.xml b/build/org.eclipse.cdt.managedbuilder.core/plugin.xml index 9b8054bc0af..a2685df62b7 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/plugin.xml +++ b/build/org.eclipse.cdt.managedbuilder.core/plugin.xml @@ -15,7 +15,7 @@ - + diff --git a/build/org.eclipse.cdt.managedbuilder.core/schema/ManagedBuildTools.exsd b/build/org.eclipse.cdt.managedbuilder.core/schema/ManagedBuildTools.exsd index bd6dfd96a96..03fc3ca5540 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/schema/ManagedBuildTools.exsd +++ b/build/org.eclipse.cdt.managedbuilder.core/schema/ManagedBuildTools.exsd @@ -109,7 +109,7 @@ This is an optional field that specifies the class that provides the dependency calculation for a given tool. This field is unused in CDT 1.2. - + @@ -239,6 +239,16 @@ Additional special types exist to flag options of special relevance to the build + + + + + + + + + + @@ -393,7 +403,7 @@ Additional special types exist to flag options of special relevance to the build - Represents a type of resource that is the target of the build process, for example, a Linux Library. A target contains a sequence of tool definitions and configurations. Targets are arranged in an inheritance hierarchy where a target inherits the list of tools from it's parent and can add to or override tools in this list. + Represents a type of resource that is the target of the build process, for example, a Linux static library. A target contains a sequence of tool definitions and configurations. Targets are arranged in an inheritance hierarchy where a target inherits the list of tools from it's parent and can add to or override tools in this list. @@ -510,6 +520,16 @@ Additional special types exist to flag options of special relevance to the build + + + + + + + + + + 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 c6be9280f37..74764229969 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 @@ -10,6 +10,8 @@ **********************************************************************/ package org.eclipse.cdt.managedbuilder.core; +import java.util.List; + /** * */ @@ -41,6 +43,14 @@ public interface ITool extends IBuildObject { */ public boolean buildsFileType(String extension); + /** + * Answers the list of valid source extensions the receiver know how to build. + * The list may be empty but will never be null. + * + * @return List + */ + public List getInputExtensions(); + /** * Answers a constant corresponding to the project nature the tool should be used * for. Possible answers are: 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 cea801d2756..0d0ac6ab330 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 @@ -41,8 +41,11 @@ import org.eclipse.cdt.core.parser.IScannerInfoProvider; import org.eclipse.cdt.managedbuilder.internal.core.Configuration; import org.eclipse.cdt.managedbuilder.internal.core.DefaultManagedConfigElement; import org.eclipse.cdt.managedbuilder.internal.core.ManagedBuildInfo; +import org.eclipse.cdt.managedbuilder.internal.core.ManagedMakeMessages; import org.eclipse.cdt.managedbuilder.internal.core.Target; import org.eclipse.cdt.managedbuilder.internal.core.Tool; +import org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator; +import org.eclipse.cdt.managedbuilder.scannerconfig.IManagedScannerInfoCollector; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; @@ -50,7 +53,8 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IExtensionPoint; -import org.eclipse.core.runtime.IPluginDescriptor; +import org.eclipse.core.runtime.IExtensionRegistry; +import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.PluginVersionIdentifier; import org.eclipse.core.runtime.QualifiedName; import org.w3c.dom.Document; @@ -69,8 +73,8 @@ public class ManagedBuildManager extends AbstractCExtension implements IScannerI private static final String ROOT_NODE_NAME = "ManagedProjectBuildInfo"; //$NON-NLS-1$ public static final String SETTINGS_FILE_NAME = ".cdtbuild"; //$NON-NLS-1$ private static final ITarget[] emptyTargets = new ITarget[0]; - public static final String INTERFACE_IDENTITY = ManagedBuilderCorePlugin.getUniqueIdentifier() + "." + "ManagedBuildManager"; //$NON-NLS-1$ //$NON-NLS-2$ - public static final String EXTENSION_POINT_ID = "ManagedBuildInfo"; //$NON-NLS-1$ + public static final String INTERFACE_IDENTITY = ManagedBuilderCorePlugin.getUniqueIdentifier() + ".ManagedBuildManager"; //$NON-NLS-1$ + public static final String EXTENSION_POINT_ID = ManagedBuilderCorePlugin.getUniqueIdentifier() + ".ManagedBuildInfo"; //$NON-NLS-1$ private static final String REVISION_ELEMENT_NAME = "managedBuildRevision"; //$NON-NLS-1$ private static final String VERSION_ELEMENT_NAME = "fileVersion"; //$NON-NLS-1$ private static final String MANIFEST_VERSION_ERROR ="ManagedBuildManager.error.manifest.version.error"; //$NON-NLS-1$ @@ -236,7 +240,73 @@ public class ManagedBuildManager extends AbstractCExtension implements IScannerI info.setSelectedTarget(target); } } - + + public static IManagedBuilderMakefileGenerator getMakefileGenerator(String targetId) { + try { + IExtensionRegistry registry = Platform.getExtensionRegistry(); + IExtensionPoint extension = registry.getExtensionPoint(EXTENSION_POINT_ID); + if (extension != null) { + // There could be many of these + IExtension[] extensions = extension.getExtensions(); + for (int i = 0; i < extensions.length; i++) { + IConfigurationElement[] configElements = extensions[i].getConfigurationElements(); + for (int j = 0; j < configElements.length; j++) { + IConfigurationElement element = configElements[j]; + if (element.getName().equals(ITarget.TARGET_ELEMENT_NAME)) { + if (element.getAttribute(ITarget.ID).equals(targetId)) { + if (element.getAttribute(ManagedBuilderCorePlugin.MAKEGEN_ID) != null) { + return (IManagedBuilderMakefileGenerator) element.createExecutableExtension(ManagedBuilderCorePlugin.MAKEGEN_ID); + } + } + } + } + } + } + } + catch (CoreException e) { + // Probably not defined + ManagedBuilderCorePlugin.log(e); + } + return null; + } + + /** + * Targets may have a scanner collector defined that knows how to discover + * built-in compiler defines and includes search paths. Find the scanner + * collector implentation for the target specified. + * + * @param string the unique id of the target to search for + * @return an implementation of IManagedScannerInfoCollector + */ + public static IManagedScannerInfoCollector getScannerInfoCollector(String targetId) { + try { + IExtensionRegistry registry = Platform.getExtensionRegistry(); + IExtensionPoint extension = registry.getExtensionPoint(EXTENSION_POINT_ID); + if (extension != null) { + // There could be many of these + IExtension[] extensions = extension.getExtensions(); + for (int i = 0; i < extensions.length; i++) { + IConfigurationElement[] configElements = extensions[i].getConfigurationElements(); + for (int j = 0; j < configElements.length; j++) { + IConfigurationElement element = configElements[j]; + if (element.getName().equals(ITarget.TARGET_ELEMENT_NAME)) { + if (element.getAttribute(ITarget.ID).equals(targetId)) { + if (element.getAttribute(ManagedBuilderCorePlugin.SCANNER_INFO_ID) != null) { + return (IManagedScannerInfoCollector) element.createExecutableExtension(ManagedBuilderCorePlugin.SCANNER_INFO_ID); + } + } + } + } + } + } + } + catch (CoreException e) { + // Probably not defined + ManagedBuilderCorePlugin.log(e); + } + return null; + } + /** * Gets the currently selected target. This is used while the project * property pages are displayed @@ -352,6 +422,7 @@ public class ManagedBuildManager extends AbstractCExtension implements IScannerI } } + /** * Saves the build information associated with a project and all resources * in the project to the build info file. @@ -501,13 +572,13 @@ public class ManagedBuildManager extends AbstractCExtension implements IScannerI if (resource instanceof IProject) { // Must be an extension target (why?) if (owner != null) - throw new BuildException(ManagedBuilderCorePlugin.getResourceString("ManagedBuildManager.error.owner_not_null")); //$NON-NLS-1$ + throw new BuildException(ManagedMakeMessages.getResourceString("ManagedBuildManager.error.owner_not_null")); //$NON-NLS-1$ } else { // Owner must be owned by the project containing this resource if (owner == null) - throw new BuildException(ManagedBuilderCorePlugin.getResourceString("ManagedBuildManager.error.null_owner")); //$NON-NLS-1$ + throw new BuildException(ManagedMakeMessages.getResourceString("ManagedBuildManager.error.null_owner")); //$NON-NLS-1$ if (!owner.equals(resource.getProject())) - throw new BuildException(ManagedBuilderCorePlugin.getResourceString("ManagedBuildManager.error.owner_not_project")); //$NON-NLS-1$ + throw new BuildException(ManagedMakeMessages.getResourceString("ManagedBuildManager.error.owner_not_project")); //$NON-NLS-1$ } // Passed validation so create the target. @@ -566,7 +637,7 @@ public class ManagedBuildManager extends AbstractCExtension implements IScannerI fileVersion = rootElement.getNodeValue(); PluginVersionIdentifier version = new PluginVersionIdentifier(fileVersion); if (!buildInfoVersion.isCompatibleWith(version)) { - throw new BuildException(ManagedBuilderCorePlugin.getResourceString(PROJECT_VERSION_ERROR)); + throw new BuildException(ManagedMakeMessages.getResourceString(PROJECT_VERSION_ERROR)); } if (buildInfoVersion.isGreaterThan(version)) { // TODO Upgrade the project @@ -599,8 +670,7 @@ public class ManagedBuildManager extends AbstractCExtension implements IScannerI return; // Get those extensions - IPluginDescriptor descriptor = ManagedBuilderCorePlugin.getDefault().getDescriptor(); - IExtensionPoint extensionPoint = descriptor.getExtensionPoint(EXTENSION_POINT_ID); + IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(EXTENSION_POINT_ID); IExtension[] extensions = extensionPoint.getExtensions(); // First call the constructors @@ -609,7 +679,7 @@ public class ManagedBuildManager extends AbstractCExtension implements IScannerI // Can we read this manifest if (!isVersionCompatible(extension)) { //The version of the Plug-in is greater than what the manager thinks it understands - throw new BuildException(ManagedBuilderCorePlugin.getResourceString(MANIFEST_VERSION_ERROR)); + throw new BuildException(ManagedMakeMessages.getResourceString(MANIFEST_VERSION_ERROR)); } IConfigurationElement[] elements = extension.getConfigurationElements(); loadConfigElements(DefaultManagedConfigElement.convertArray(elements)); diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedBuilderCorePlugin.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedBuilderCorePlugin.java index 5b2330314de..66fda3f3885 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedBuilderCorePlugin.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedBuilderCorePlugin.java @@ -11,38 +11,44 @@ package org.eclipse.cdt.managedbuilder.core; * IBM Rational Software - Initial API and implementation * **********************************************************************/ -import java.text.MessageFormat; -import java.util.MissingResourceException; -import java.util.ResourceBundle; +import java.lang.reflect.InvocationTargetException; -import org.eclipse.cdt.managedbuilder.scannerconfig.IManagedScannerInfoCollector; +import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IConfigurationElement; -import org.eclipse.core.runtime.IExtension; -import org.eclipse.core.runtime.IExtensionPoint; -import org.eclipse.core.runtime.IPluginDescriptor; +import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Plugin; +import org.eclipse.core.runtime.Status; public class ManagedBuilderCorePlugin extends Plugin { + private static final String PLUGIN_ID = "org.eclipse.cdt.managedbuilder.core"; //$NON-NLS-1$ + // The attribute name for the dependency calculator + public static final String DEP_CALC_ID ="dependencyCalculator"; //$NON-NLS-1$ //The shared instance. private static ManagedBuilderCorePlugin plugin; - //Resource bundle. - private static ResourceBundle resourceBundle; - + // The attribute name for the scanner info collector + public static final String SCANNER_INFO_ID = "scannerInfoCollector"; //$NON-NLS-1$ + // The attribute name for the makefile generator + public static final String MAKEGEN_ID ="makefileGenerator"; //$NON-NLS-1$ + /** * @param descriptor */ - public ManagedBuilderCorePlugin(IPluginDescriptor descriptor) { - super(descriptor); + public ManagedBuilderCorePlugin() { + super(); plugin = this; - try { - resourceBundle = ResourceBundle.getBundle("org.eclipse.cdt.managedbuilder.internal.core.PluginResources"); //$NON-NLS-1$ - } catch (MissingResourceException x) { - resourceBundle = null; - } } + public static String getUniqueIdentifier() { + if (getDefault() == null) { + // If the default instance is not yet initialized, + // return a static identifier. This identifier must + // match the plugin id defined in plugin.xml + return PLUGIN_ID; + } + return getDefault().getBundle().getSymbolicName(); + } + /** * Returns the shared instance. */ @@ -50,69 +56,19 @@ public class ManagedBuilderCorePlugin extends Plugin { return plugin; } - - public static String getResourceString(String key) { - try { - return resourceBundle.getString(key); - } catch (MissingResourceException e) { - return "!" + key + "!"; //$NON-NLS-1$ //$NON-NLS-2$ - } catch (NullPointerException e) { - return "#" + key + "#"; //$NON-NLS-1$ //$NON-NLS-2$ - } + public static void log(Throwable e) { + if (e instanceof InvocationTargetException) + e = ((InvocationTargetException) e).getTargetException(); + IStatus status = null; + if (e instanceof CoreException) + status = ((CoreException) e).getStatus(); + else + status = new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.OK, e.getMessage(), e); + log(status); } - public static String getFormattedString(String key, String arg) { - return MessageFormat.format(getResourceString(key), new String[] { arg }); - } - - public static String getFormattedString(String key, String[] args) { - return MessageFormat.format(getResourceString(key), args); - } - - /** - * Convenience method which returns the unique identifier of this plugin. - */ - public static String getUniqueIdentifier() { - if (getDefault() == null) { - // If the default instance is not yet initialized, - // return a static identifier. This identifier must - // match the plugin id defined in plugin.xml - return "org.eclipse.cdt.managedbuilder.core"; //$NON-NLS-1$ - } - return getDefault().getDescriptor().getUniqueIdentifier(); - } - - /** - * Targets may have a scanner collector defined that knows how to discover - * built-in compiler defines and includes search paths. Find the scanner - * collector implentation for the target specified. - * - * @param string the unique id of the target to search for - * @return an implementation of IManagedScannerInfoCollector - */ - public IManagedScannerInfoCollector getScannerInfoCollector(String targetId) { - try { - IExtensionPoint extension = getDescriptor().getExtensionPoint(ManagedBuildManager.EXTENSION_POINT_ID); - if (extension != null) { - // There could be many of these - IExtension[] extensions = extension.getExtensions(); - for (int i = 0; i < extensions.length; i++) { - IConfigurationElement[] configElements = extensions[i].getConfigurationElements(); - for (int j = 0; j < configElements.length; j++) { - IConfigurationElement element = configElements[j]; - if (element.getName().equals("target")) { //$NON-NLS-1$ - if (element.getAttribute(ITarget.ID).equals(targetId)) { - return (IManagedScannerInfoCollector) element.createExecutableExtension("scannerInfoCollector"); //$NON-NLS-1$ - } - } - } - } - } - } - catch (CoreException e) { - // Probably not defined - } - return null; + public static void log(IStatus status) { + ResourcesPlugin.getPlugin().getLog().log(status); } } diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedCProjectNature.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedCProjectNature.java index 4d04c6c8352..44d18723ca8 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedCProjectNature.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ManagedCProjectNature.java @@ -21,8 +21,8 @@ import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IProjectNature; import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IPluginDescriptor; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Plugin; public class ManagedCProjectNature implements IProjectNature { @@ -110,9 +110,8 @@ public class ManagedCProjectNature implements IProjectNature { */ public static String getBuilderID() { Plugin plugin = (Plugin)ManagedBuilderCorePlugin.getDefault(); - IPluginDescriptor descriptor = plugin.getDescriptor(); - if (descriptor.getExtension(BUILDER_NAME) != null) { - return descriptor.getUniqueIdentifier() + "." + BUILDER_NAME; //$NON-NLS-1$ + if (Platform.getExtensionRegistry().getExtension(BUILDER_NAME) != null) { + return ManagedBuilderCorePlugin.getUniqueIdentifier() + "." + BUILDER_NAME; //$NON-NLS-1$ } return BUILDER_ID; } 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 be83f61b6db..2174ef0fee6 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 @@ -28,8 +28,11 @@ import org.eclipse.cdt.core.model.ICModelMarker; import org.eclipse.cdt.core.resources.ACBuilder; import org.eclipse.cdt.core.resources.IConsole; import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo; +import org.eclipse.cdt.managedbuilder.core.ITool; import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin; +import org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderDependencyCalculator; +import org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; @@ -39,11 +42,15 @@ import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.IncrementalProjectBuilder; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.SubProgressMonitor; public class GeneratedMakefileBuilder extends ACBuilder { @@ -65,7 +72,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { // Local variables protected List resourcesToBuild; protected List ruleList; - + protected IManagedBuilderMakefileGenerator generator; public class ResourceDeltaVisitor implements IResourceDeltaVisitor { private boolean buildNeeded = false; @@ -96,7 +103,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { * @see org.eclipse.core.internal.events.InternalBuilder#build(int, java.util.Map, org.eclipse.core.runtime.IProgressMonitor) */ protected IProject[] build(int kind, Map args, IProgressMonitor monitor) throws CoreException { - String statusMsg = ManagedBuilderCorePlugin.getFormattedString(START, getProject().getName()); + String statusMsg = ManagedMakeMessages.getFormattedString(START, getProject().getName()); IProject[] deps = getProject().getReferencedProjects(); if (statusMsg != null) { monitor.subTask(statusMsg); @@ -171,7 +178,9 @@ public class GeneratedMakefileBuilder extends ACBuilder { IProject depProject = deps[i]; if (ManagedBuildManager.manages(depProject)) { IManagedBuildInfo depInfo = ManagedBuildManager.getBuildInfo(depProject); - MakefileGenerator generator = new MakefileGenerator(depProject, depInfo, monitor); + String targetID = depInfo.getDefaultTarget().getParent().getId(); + IManagedBuilderMakefileGenerator generator = ManagedBuildManager.getMakefileGenerator(targetID); + generator.initialize(depProject, depInfo, monitor); try { generator.regenerateMakefiles(); } catch (CoreException e) { @@ -182,11 +191,13 @@ public class GeneratedMakefileBuilder extends ACBuilder { } // Need to report status to the user - String statusMsg = ManagedBuilderCorePlugin.getFormattedString(REBUILD, getProject().getName()); + String statusMsg = ManagedMakeMessages.getFormattedString(REBUILD, getProject().getName()); monitor.subTask(statusMsg); // Regenerate the makefiles for this project - MakefileGenerator generator = new MakefileGenerator(getProject(), info, monitor); + String targetID = info.getDefaultTarget().getParent().getId(); + generator = ManagedBuildManager.getMakefileGenerator(targetID); + generator.initialize(getProject(), info, monitor); try { generator.regenerateMakefiles(); } catch (CoreException e) { @@ -195,14 +206,53 @@ public class GeneratedMakefileBuilder extends ACBuilder { } // Now call make - IPath topBuildDir = generator.getTopBuildDir(); + IPath topBuildDir = generator.getBuildWorkingDir(); if (topBuildDir != null) { - invokeMake(true, topBuildDir.removeFirstSegments(1), info, monitor); + invokeMake(true, topBuildDir, info, monitor); } else { monitor.done(); } + + // Now regenerate the dependencies + try { + generator.regenerateDependencies(false); + } catch (CoreException e) { + // Throw the exception back to the builder + throw e; + } + } + /** + * @param toolId + * @return + */ + public IManagedBuilderDependencyCalculator getDependencyCalculator(String toolId) { + try { + IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(ManagedBuilderCorePlugin.getUniqueIdentifier(), ManagedBuilderCorePlugin.DEP_CALC_ID); + if (extension != null) { + // There could be many of these + IExtension[] extensions = extension.getExtensions(); + for (int i = 0; i < extensions.length; i++) { + IConfigurationElement[] configElements = extensions[i].getConfigurationElements(); + for (int j = 0; j < configElements.length; j++) { + IConfigurationElement element = configElements[j]; + if (element.getName().equals(ITool.TOOL_ELEMENT_NAME)) { + if (element.getAttribute(ITool.ID).equals(toolId)) { + if (element.getAttribute(ManagedBuilderCorePlugin.DEP_CALC_ID) != null) { + return (IManagedBuilderDependencyCalculator) element.createExecutableExtension(ManagedBuilderCorePlugin.DEP_CALC_ID); + } + } + } + } + } + } + } + catch (CoreException e) { + // Probably not defined + } + return null; + } /* (non-javadoc) * Answers an array of strings with the proper make targets * @@ -262,7 +312,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { if (monitor == null) { monitor = new NullProgressMonitor(); } - statusMsg = ManagedBuilderCorePlugin.getFormattedString(INCREMENTAL, getProject().getName()); + statusMsg = ManagedMakeMessages.getFormattedString(INCREMENTAL, getProject().getName()); monitor.subTask(statusMsg); // Regenerate the makefiles for any managed projects this project depends on @@ -271,7 +321,9 @@ public class GeneratedMakefileBuilder extends ACBuilder { IProject depProject = deps[i]; if (ManagedBuildManager.manages(depProject)) { IManagedBuildInfo depInfo = ManagedBuildManager.getBuildInfo(depProject); - MakefileGenerator generator = new MakefileGenerator(depProject, depInfo, monitor); + String targetID = depInfo.getDefaultTarget().getParent().getId(); + IManagedBuilderMakefileGenerator generator = ManagedBuildManager.getMakefileGenerator(targetID); + generator.initialize(depProject, depInfo, monitor); try { generator.regenerateMakefiles(); } catch (CoreException e) { @@ -282,7 +334,9 @@ public class GeneratedMakefileBuilder extends ACBuilder { } // Ask the makefile generator to generate any makefiles needed to build delta - MakefileGenerator generator = new MakefileGenerator(getProject(), info, monitor); + String targetID = info.getDefaultTarget().getParent().getId(); + generator = ManagedBuildManager.getMakefileGenerator(targetID); + generator.initialize(getProject(), info, monitor); try { generator.generateMakefiles(delta); } catch (CoreException e) { @@ -319,7 +373,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { if (root == null) { return; } - IPath makefile = workingDirectory.addTrailingSeparator().append(MakefileGenerator.MAKEFILE_NAME); + IPath makefile = workingDirectory.addTrailingSeparator().append(generator.getMakefileName()); if (root.getFileForLocation(makefile) == null) { return; } @@ -330,7 +384,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { String[] msgs = new String[2]; msgs[0] = makeCommand.toString(); msgs[1] = currentProject.getName(); - monitor.beginTask(ManagedBuilderCorePlugin.getFormattedString(MAKE, msgs), IProgressMonitor.UNKNOWN); + monitor.beginTask(ManagedMakeMessages.getFormattedString(MAKE, msgs), IProgressMonitor.UNKNOWN); // Get a build console for the project StringBuffer buf = new StringBuffer(); @@ -339,14 +393,14 @@ public class GeneratedMakefileBuilder extends ACBuilder { ConsoleOutputStream consoleOutStream = console.getOutputStream(); String[] consoleHeader = new String[3]; consoleHeader[0] = fullBuild ? - ManagedBuilderCorePlugin.getResourceString(TYPE_FULL) : - ManagedBuilderCorePlugin.getResourceString(TYPE_INC); + ManagedMakeMessages.getResourceString(TYPE_FULL) : + ManagedMakeMessages.getResourceString(TYPE_INC); consoleHeader[1] = info.getConfigurationName(); consoleHeader[2] = currentProject.getName(); - buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$ - buf.append(ManagedBuilderCorePlugin.getFormattedString(CONSOLE_HEADER, consoleHeader)); - buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$ - buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$ + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$ //$NON-NLS-2$ + buf.append(ManagedMakeMessages.getFormattedString(CONSOLE_HEADER, consoleHeader)); + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$ //$NON-NLS-2$ + buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$ //$NON-NLS-2$ consoleOutStream.write(buf.toString().getBytes()); consoleOutStream.flush(); @@ -392,7 +446,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { // Hook up an error parser manager String[] errorParsers = info.getDefaultTarget().getErrorParserList(); - ErrorParserManager epm = new ErrorParserManager(getProject(), this, errorParsers); + ErrorParserManager epm = new ErrorParserManager(getProject(), workingDirectory, this, errorParsers); epm.setOutputStream(consoleOutStream); OutputStream stdout = epm.getOutputStream(); OutputStream stderr = epm.getOutputStream(); @@ -413,7 +467,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { // Force a resync of the projects without allowing the user to cancel. // This is probably unkind, but short of this there is no way to insure // the UI is up-to-date with the build results - monitor.subTask(ManagedBuilderCorePlugin.getResourceString(REFRESH)); + monitor.subTask(ManagedMakeMessages.getResourceString(REFRESH)); try { currentProject.refreshLocal(IResource.DEPTH_INFINITE, null); for (int j = 0; j < deps.length; ++j) { @@ -421,7 +475,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { project.refreshLocal(IResource.DEPTH_INFINITE, null); } } catch (CoreException e) { - monitor.subTask(ManagedBuilderCorePlugin.getResourceString(REFRESH_ERROR)); + monitor.subTask(ManagedMakeMessages.getResourceString(REFRESH_ERROR)); } } else { errMsg = launcher.getErrorMessage(); @@ -430,13 +484,13 @@ public class GeneratedMakefileBuilder extends ACBuilder { // Report either the success or failure of our mission buf = new StringBuffer(); if (errMsg != null && errMsg.length() > 0) { - String errorDesc = ManagedBuilderCorePlugin.getResourceString(BUILD_ERROR); + String errorDesc = ManagedMakeMessages.getResourceString(BUILD_ERROR); buf.append(errorDesc); buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$//$NON-NLS-2$ buf.append("(").append(errMsg).append(")"); //$NON-NLS-1$ //$NON-NLS-2$ } else { // Report a successful build - String successMsg = ManagedBuilderCorePlugin.getFormattedString(BUILD_FINISHED, currentProject.getName()); + String successMsg = ManagedMakeMessages.getFormattedString(BUILD_FINISHED, currentProject.getName()); buf.append(successMsg); buf.append(System.getProperty("line.separator", "\n")); //$NON-NLS-1$//$NON-NLS-2$ } @@ -447,7 +501,7 @@ public class GeneratedMakefileBuilder extends ACBuilder { stdout.close(); stderr.close(); - monitor.subTask(ManagedBuilderCorePlugin.getResourceString(MARKERS)); + monitor.subTask(ManagedMakeMessages.getResourceString(MARKERS)); epm.reportProblems(); } } catch (Exception e) { diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/MakefileGenerator.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/MakefileGenerator.java deleted file mode 100644 index 072e6346828..00000000000 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/MakefileGenerator.java +++ /dev/null @@ -1,1100 +0,0 @@ -package org.eclipse.cdt.managedbuilder.internal.core; - -/********************************************************************** - * Copyright (c) 2003,2004 Rational Software Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v0.5 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v05.html - * - * Contributors: - * IBM Rational Software - Initial API and implementation - * **********************************************************************/ - -import java.io.ByteArrayInputStream; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; - -import org.eclipse.cdt.core.CCorePlugin; -import org.eclipse.cdt.core.search.ICSearchConstants; -import org.eclipse.cdt.core.search.ICSearchScope; -import org.eclipse.cdt.core.search.SearchEngine; -import org.eclipse.cdt.internal.core.model.Util; -import org.eclipse.cdt.internal.core.search.PathCollector; -import org.eclipse.cdt.internal.core.search.PatternSearchJob; -import org.eclipse.cdt.internal.core.search.indexing.IndexManager; -import org.eclipse.cdt.internal.core.search.matching.CSearchPattern; -import org.eclipse.cdt.internal.core.sourcedependency.DependencyQueryJob; -import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo; -import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; -import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin; -import org.eclipse.core.resources.IContainer; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IFolder; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceDelta; -import org.eclipse.core.resources.IResourceDeltaVisitor; -import org.eclipse.core.resources.IResourceProxy; -import org.eclipse.core.resources.IResourceProxyVisitor; -import org.eclipse.core.resources.IResourceStatus; -import org.eclipse.core.resources.IWorkspaceRoot; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.core.runtime.OperationCanceledException; -import org.eclipse.core.runtime.Path; - -public class MakefileGenerator { - - // this is used to draw a "comment line" - private static final int COLS_PER_LINE = 80; - - // String constants for messages - private static final String MESSAGE = "ManagedMakeBuilder.message"; //$NON-NLS-1$ - private static final String BUILD_ERROR = MESSAGE + ".error"; //$NON-NLS-1$ - private static final String COMMENT = "ManagedMakeBuilder.comment"; //$NON-NLS-1$ - private static final String HEADER = COMMENT + ".header"; //$NON-NLS-1$ - private static final String MOD_LIST = COMMENT + ".module.list"; //$NON-NLS-1$ - private static final String SRC_LISTS = COMMENT + ".source.list"; //$NON-NLS-1$ - private static final String MOD_RULES = COMMENT + ".build.rule"; //$NON-NLS-1$ - private static final String MOD_INCL = COMMENT + ".module.make.includes"; //$NON-NLS-1$ - private static final String DEP_INCL = COMMENT + ".module.dep.includes"; //$NON-NLS-1$ - private static final String AUTO_DEP = COMMENT + ".autodeps"; //$NON-NLS-1$ - - // String constants for makefile contents - protected static final String COLON = ":"; //$NON-NLS-1$ - protected static final String DEPFILE_NAME = "subdir.dep"; //$NON-NLS-1$ - protected static final String DOT = "."; //$NON-NLS-1$ - protected static final String MAKEFILE_NAME = "makefile"; //$NON-NLS-1$ - protected static final String MODFILE_NAME = "subdir.mk"; //$NON-NLS-1$ - protected static final String LINEBREAK = "\\"; //$NON-NLS-1$ - protected static final String NEWLINE = System.getProperty("line.separator"); //$NON-NLS-1$ - protected static final String LOGICAL_AND = "&&"; //$NON-NLS-1$ - protected static final String SEPARATOR = "/"; //$NON-NLS-1$ - protected static final String TAB = "\t"; //$NON-NLS-1$ - protected static final String WHITESPACE = " "; //$NON-NLS-1$ - protected static final String WILDCARD = "%"; //$NON-NLS-1$ - protected static final String COMMENT_SYMBOL = "#"; //$NON-NLS-1$ - protected static final String MAKEFILE_INIT = "makefile.init"; //$NON-NLS-1$ - protected static final String MAKEFILE_DEFS = "makefile.defs"; //$NON-NLS-1$ - protected static final String MAKEFILE_TARGETS = "makefile.targets"; //$NON-NLS-1$ - - // Local variables needed by generator - protected IManagedBuildInfo info; - protected List modifiedList; - protected IProgressMonitor monitor; - protected List subdirList; - protected IProject project; - protected List ruleList; - protected IPath topBuildDir; - private String target; - private String extension; - - /** - * This class is used to recursively walk the project and determine which - * modules contribute buildable source files. - */ - protected class ResourceProxyVisitor implements IResourceProxyVisitor { - private MakefileGenerator generator; - private IManagedBuildInfo info; - - /** - * Constructs a new resource proxy visitor to quickly visit project - * resources. - */ - public ResourceProxyVisitor(MakefileGenerator generator, IManagedBuildInfo info) { - this.generator = generator; - this.info = info; - } - - /* (non-Javadoc) - * @see org.eclipse.core.resources.IResourceProxyVisitor#visit(org.eclipse.core.resources.IResourceProxy) - */ - public boolean visit(IResourceProxy proxy) throws CoreException { - // No point in proceeding, is there - if (generator == null) { - return false; - } - - // Is this a resource we should even consider - if (proxy.getType() == IResource.FILE) { - // Check extension to see if build model should build this file - IResource resource = proxy.requestResource(); - String ext = resource.getFileExtension(); - if (info.buildsFileType(ext)) { - if (!generator.isGeneratedResource(resource)) { - generator.appendBuildSubdirectory(resource); - } - } - return false; - } - - // Recurse into subdirectories - return true; - } - - } - - public class ResourceDeltaVisitor implements IResourceDeltaVisitor { - private MakefileGenerator generator; - private IManagedBuildInfo info; - - /** - * - */ - public ResourceDeltaVisitor(MakefileGenerator generator, IManagedBuildInfo info) { - this.generator = generator; - this.info = info; - } - - /* (non-javadoc) - * Answers a list of resource names in the workspace that depend on the resource - * specified in the argument. - * - * @param resource the root of the dependency tree - * @return IResource[] - */ - private IResource[] findDependencies(IResource resource) { - PathCollector pathCollector = new PathCollector(); - ICSearchScope scope = SearchEngine.createWorkspaceScope(); - CSearchPattern pattern = CSearchPattern.createPattern(resource.getLocation().toOSString(), ICSearchConstants.INCLUDE, ICSearchConstants.REFERENCES, ICSearchConstants.EXACT_MATCH, true); - IndexManager indexManager = CCorePlugin.getDefault().getCoreModel().getIndexManager(); - indexManager.performConcurrentJob( - new PatternSearchJob( - (CSearchPattern) pattern, - scope, - pathCollector, - indexManager), - ICSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, - null, null); - - // We will get back an array of resource names relative to the workspace - String[] deps = pathCollector.getPaths(); - - // Convert them to something useful - List depList = new ArrayList(); - IResource res = null; - IWorkspaceRoot root = null; - if (generator.project != null) { - root = generator.project.getWorkspace().getRoot(); - } - for (int index = 0; index < deps.length; ++index) { - res = root.findMember(deps[index]); - if (res != null) { - depList.add(res); - } - } - - return (IResource[]) depList.toArray(new IResource[depList.size()]); - } - - private void handleHeaderDependency(IResource resource, boolean moved) { - // If this is a move and the resource is external to the project, touch that resource - if (resource.getProject().equals(generator.project)) { - generator.appendModifiedSubdirectory(resource); - } else { - if (moved) { - try { - resource.touch(new NullProgressMonitor()); - } catch (CoreException e) { - } - } - } - } - - /* (non-Javadoc) - * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta) - */ - public boolean visit(IResourceDelta delta) throws CoreException { - // Should the visitor keep iterating in current directory - boolean keepLooking = false; - IResource resource = delta.getResource(); - - // What kind of resource change has occurred - if (resource.getType() == IResource.FILE) { - String ext = resource.getFileExtension(); - boolean moved = false; - switch (delta.getKind()) { - case IResourceDelta.ADDED: - moved = delta.getFlags() == IResourceDelta.MOVED_TO; - if (!generator.isGeneratedResource(resource)) { - // This is a source file so just add its container - if (info.buildsFileType(ext)) { - generator.appendModifiedSubdirectory(resource); - } else if (info.isHeaderFile(ext)) { - // Add the container of the resource and any resources that depend on it - generator.appendModifiedSubdirectory(resource); - IResource[] deps = findDependencies(resource); - for (int i = 0; i < deps.length; ++i){ - handleHeaderDependency(deps[i], moved); - } - } - } - break; - case IResourceDelta.REMOVED: - moved = delta.getFlags() == IResourceDelta.MOVED_FROM; - if (!generator.isGeneratedResource(resource)) { - // This is a source file so just add its container - if (info.buildsFileType(ext)) { - generator.appendModifiedSubdirectory(resource); - } else if (info.isHeaderFile(ext)) { - // Add the container of the resource and any resources that depend on it - generator.appendModifiedSubdirectory(resource); - IResource[] deps = findDependencies(resource); - for (int i = 0; i < deps.length; ++i){ - handleHeaderDependency(deps[i], moved); - } - } - } - break; - case IResourceDelta.CHANGED: - if (!generator.isGeneratedResource(resource)) { - if (info.buildsFileType(ext)) { - keepLooking = true; - } else if (info.isHeaderFile(ext)) { - // Add the container of the resource and any resources that depend on it - generator.appendModifiedSubdirectory(resource); - IResource[] deps= findDependencies(resource); - for (int i = 0; i < deps.length; ++i){ - handleHeaderDependency(deps[i], moved); - } - // That does it for this directory, so don't bother to keep looking - } - } - break; - default: - keepLooking = true; - break; - } - } if (resource.getType() == IResource.PROJECT) { - // If there is a zero-length delta, something the project depends on has changed so just call make - IResourceDelta[] children = delta.getAffectedChildren(); - if (children != null && children.length > 0) { - keepLooking = true; - } - } else { - // If the resource is part of the generated directory structure don't recurse - if (!generator.isGeneratedResource(resource)) { - keepLooking = true; - } - } - - return keepLooking; - } - } - - /** - * @param project - * @param info - * @param monitor - */ - public MakefileGenerator(IProject project, IManagedBuildInfo info, IProgressMonitor monitor) { - super(); - // 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 - target = info.getBuildArtifactName(); - // Get its extension - extension = info.getBuildArtifactExtension(); - if (extension == null) { - extension = new String(); - } - } - - /* (non-javadoc) - * Calculates dependencies for all the source files in the argument. A source - * file can depend on any number of header files, so the dependencies have to - * be added to its dependency list. - * - * @param module - * @return - */ - protected StringBuffer addSourceDependencies(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$ - - // Create the buffer to hold the output for the module and a dep calculator - StringBuffer buffer = new StringBuffer(); - buffer.append(COMMENT_SYMBOL + WHITESPACE + ManagedBuilderCorePlugin.getResourceString(AUTO_DEP) + NEWLINE); - IndexManager indexManager = CCorePlugin.getDefault().getCoreModel().getIndexManager(); - - /* - * Visit each resource in the folder that we have a rule to build. - * The dependency output for each resource will be in the format - * /. : ... - * with long lines broken. - */ - IResource[] resources = module.members(); - for (int i = 0; i < resources.length; i++) { - IResource resource = resources[i]; - if (resource.getType() == IResource.FILE) { - String inputExt = resource.getFileExtension(); - if (info.buildsFileType(inputExt)) { - // Get the filename without an extension - String fileName = resource.getFullPath().removeFileExtension().lastSegment(); - if (fileName == null) continue; - String outputExt = info.getOutputExtension(inputExt); - if (outputExt != null) { - fileName += DOT + outputExt; - } - // Ask the dep generator to find all the deps for this resource - ArrayList dependencies = new ArrayList(); - try { - indexManager.performConcurrentJob(new DependencyQueryJob(project, (IFile)resource, indexManager, dependencies), ICSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, null, null); - } catch (Exception e) { - continue; - } - if (dependencies.size() == 0) continue; - buffer.append(relativePath + fileName + COLON + WHITESPACE); - Iterator iter = dependencies.listIterator(); - while (iter.hasNext()) { - buffer.append(LINEBREAK + NEWLINE); - String rawPath = (String)iter.next(); - // TODO Convert to relative if possible - String path = escapeWhitespaces(rawPath); - buffer.append(path); - if (iter.hasNext()) { - buffer.append(WHITESPACE); - } - } - buffer.append(NEWLINE); - } - } - } - return buffer; - } - - /* (non-Javadoc) - * Answers the argument with all whitespaces replaced with an escape sequence. - * - * @param path - */ - private 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; - } - } - - protected StringBuffer addTopHeader() { - return addDefaultHeader(); - } - - protected StringBuffer addFragmentMakefileHeader() { - return addDefaultHeader(); - } - - protected StringBuffer addFragmentDependenciesHeader() { - return addDefaultHeader(); - } - - protected void outputCommentLine(StringBuffer buffer) { - for (int i = 0; i < COLS_PER_LINE; i++) { - buffer.append(COMMENT_SYMBOL); - } - buffer.append(NEWLINE); - } - - protected StringBuffer addDefaultHeader() { - StringBuffer buffer = new StringBuffer(); - outputCommentLine(buffer); - buffer.append(COMMENT_SYMBOL+WHITESPACE+ManagedBuilderCorePlugin.getResourceString(HEADER)+NEWLINE); - outputCommentLine(buffer); - buffer.append(NEWLINE); - return buffer; - } - - /* (non-javadoc) - * @param buffer - * @param info - */ - protected 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); - - buffer.append(COMMENT_SYMBOL + WHITESPACE + ManagedBuilderCorePlugin.getResourceString(SRC_LISTS) + NEWLINE); - buffer.append("C_SRCS := " + NEWLINE); //$NON-NLS-1$ - buffer.append("CC_SRCS := " + NEWLINE); //$NON-NLS-1$ - buffer.append("CXX_SRCS := " + NEWLINE); //$NON-NLS-1$ - buffer.append("CAPC_SRCS := " + NEWLINE); //$NON-NLS-1$ - buffer.append("CPP_SRCS := " + NEWLINE + NEWLINE); //$NON-NLS-1$ - - // Add the libraries this project depends on - buffer.append("LIBS := "); //$NON-NLS-1$ - String[] libs = info.getLibsForTarget(extension); - for (int i = 0; i < libs.length; i++) { - String string = libs[i]; - buffer.append(LINEBREAK + NEWLINE + string); - } - buffer.append(NEWLINE + NEWLINE); - - // Add the extra user-specified objects - buffer.append("USER_OBJS := "); //$NON-NLS-1$ - String[] userObjs = info.getUserObjectsForTarget(extension); - for (int j = 0; j < userObjs.length; j++) { - String string = userObjs[j]; - buffer.append(LINEBREAK + NEWLINE + string); - } - buffer.append(NEWLINE + NEWLINE); - - buffer.append("OBJS = $(C_SRCS:$(ROOT)/%.c=%.o) $(CC_SRCS:$(ROOT)/%.cc=%.o) $(CXX_SRCS:$(ROOT)/%.cxx=%.o) $(CAPC_SRCS:$(ROOT)/%.C=%.o) $(CPP_SRCS:$(ROOT)/%.cpp=%.o)" + NEWLINE); //$NON-NLS-1$ - return (buffer.append(NEWLINE)); - } - - /* (non-javadoc) - * @return - */ - protected StringBuffer addSubdirectories() { - StringBuffer buffer = new StringBuffer(); - // Add the comment - buffer.append(COMMENT_SYMBOL + WHITESPACE + ManagedBuilderCorePlugin.getResourceString(MOD_LIST) + NEWLINE); - buffer.append("SUBDIRS := " + LINEBREAK + NEWLINE); //$NON-NLS-1$ - - // Get all the module names - ListIterator iter = getSubdirList().listIterator(); - while (iter.hasNext()) { - IContainer container = (IContainer) iter.next(); - // Check the special case where the module is the project root - if (container.getFullPath() == project.getFullPath()) { - buffer.append(DOT + WHITESPACE + LINEBREAK + NEWLINE); - } else { - IPath path = container.getProjectRelativePath(); - buffer.append(path.toString() + WHITESPACE + LINEBREAK + NEWLINE); - } - } - - // Now add the makefile instruction to include all the subdirectory makefile fragments - buffer.append(NEWLINE); - buffer.append(COMMENT_SYMBOL +WHITESPACE + ManagedBuilderCorePlugin.getResourceString(MOD_INCL) + NEWLINE); - buffer.append("-include ${patsubst %, %/subdir.mk, $(SUBDIRS)}" + NEWLINE); //$NON-NLS-1$ - buffer.append(NEWLINE); - - // Include makefile.defs supplemental makefile - buffer.append("-include $(ROOT)" + SEPARATOR + MAKEFILE_DEFS + NEWLINE); //$NON-NLS-1$ - - buffer.append(NEWLINE); - return buffer; - } - - - /* (non-javadoc) - * Answers a StringBuffer containing all of the sources contributed by - * a container to the build. - * - * @param module - * @return StringBuffer - */ - 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$ - - // String buffers - StringBuffer buffer = new StringBuffer(); - StringBuffer cBuffer = new StringBuffer("C_SRCS += " + LINEBREAK + NEWLINE); //$NON-NLS-1$ - cBuffer.append("${addprefix $(ROOT)/" + relativePath + "," + LINEBREAK + NEWLINE); //$NON-NLS-1$//$NON-NLS-2$ - StringBuffer ccBuffer = new StringBuffer("CC_SRCS += \\" + NEWLINE); //$NON-NLS-1$ - ccBuffer.append("${addprefix $(ROOT)/" + relativePath + "," + LINEBREAK + NEWLINE); //$NON-NLS-1$//$NON-NLS-2$ - StringBuffer cxxBuffer = new StringBuffer("CXX_SRCS += \\" + NEWLINE); //$NON-NLS-1$ - cxxBuffer.append("${addprefix $(ROOT)/" + relativePath + "," + LINEBREAK + NEWLINE); //$NON-NLS-1$//$NON-NLS-2$ - StringBuffer capcBuffer = new StringBuffer("CAPC_SRCS += \\" + NEWLINE); //$NON-NLS-1$ - capcBuffer.append("${addprefix $(ROOT)/" + relativePath + "," + LINEBREAK + NEWLINE); //$NON-NLS-1$//$NON-NLS-2$ - StringBuffer cppBuffer = new StringBuffer("CPP_SRCS += \\" + NEWLINE); //$NON-NLS-1$ - cppBuffer.append("${addprefix $(ROOT)/" + relativePath + "," + LINEBREAK + NEWLINE); //$NON-NLS-1$//$NON-NLS-2$ - StringBuffer ruleBuffer = new StringBuffer(COMMENT_SYMBOL + WHITESPACE + ManagedBuilderCorePlugin.getResourceString(MOD_RULES) + NEWLINE); - - // Put the comment in - buffer.append(COMMENT_SYMBOL + WHITESPACE + ManagedBuilderCorePlugin.getResourceString(SRC_LISTS) + NEWLINE); - - // Visit the resources in this folder - IResource[] resources = module.members(); - for (int i = 0; i < resources.length; i++) { - IResource resource = resources[i]; - if (resource.getType() == IResource.FILE) { - String ext = resource.getFileExtension(); - if (info.buildsFileType(ext)) { - if (new String("c").equals(ext)) { //$NON-NLS-1$ - cBuffer.append(resource.getName() + WHITESPACE + LINEBREAK + NEWLINE); - } else if (new String("cc").equalsIgnoreCase(ext)) { //$NON-NLS-1$ - ccBuffer.append(resource.getName() + WHITESPACE + LINEBREAK + NEWLINE); - } else if (new String("cxx").equalsIgnoreCase(ext)) { //$NON-NLS-1$ - cxxBuffer.append(resource.getName() + WHITESPACE + LINEBREAK + NEWLINE); - } else if (new String("C").equals(ext)) { //$NON-NLS-1$ - capcBuffer.append(resource.getName() + WHITESPACE + LINEBREAK + NEWLINE); - } else { - cppBuffer.append(resource.getName() + WHITESPACE + LINEBREAK + NEWLINE); - } - - // Try to add the rule for the file - addRule(relativePath, ruleBuffer, resource); - } - } - } - - // Finish the commands in the buffers - buffer.append(cBuffer.append("}" + NEWLINE + NEWLINE)); //$NON-NLS-1$ - buffer.append(ccBuffer.append("}" + NEWLINE + NEWLINE)); //$NON-NLS-1$ - buffer.append(cxxBuffer.append("}" + NEWLINE + NEWLINE)); //$NON-NLS-1$ - buffer.append(capcBuffer.append("}" + NEWLINE + NEWLINE)); //$NON-NLS-1$ - buffer.append(cppBuffer.append("}" + NEWLINE + NEWLINE)); //$NON-NLS-1$ - - return buffer.append(ruleBuffer + NEWLINE); - } - - /* (non-javadoc) - * Answers a StrinBuffer containing all of the required targets to - * properly build the project. - * - * @return StringBuffer - */ - protected StringBuffer addTargets(boolean rebuild) { - StringBuffer buffer = new StringBuffer(); - - // Assemble the information needed to generate the targets - String cmd = info.getToolForTarget(extension); - String flags = info.getFlagsForTarget(extension); - String outflag = info.getOutputFlag(extension); - String outputPrefix = info.getOutputPrefix(extension); - String targets = rebuild ? "clean all" : "all"; //$NON-NLS-1$ //$NON-NLS-2$ - - // Get all the projects the build target depends on - IProject[] deps = null; - try { - deps = 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 .... - } - - // Write out the all target first in case someone just runs make - // all: targ_ [deps] - String defaultTarget = "all:"; //$NON-NLS-1$ - if (deps.length > 0) { - defaultTarget += WHITESPACE + "deps"; //$NON-NLS-1$ - } - buffer.append(defaultTarget + WHITESPACE + outputPrefix + target); - 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]> - */ - List managedProjectOutputs = new ArrayList(); - if (deps.length > 0) { - buffer.append("deps:" + NEWLINE); //$NON-NLS-1$ - if (deps != null) { - for (int i = 0; i < deps.length; i++) { - IProject dep = deps[i]; - 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.isDirty()) { - depTargets = "clean all"; //$NON-NLS-1$ - } - String dependency = buildDir + SEPARATOR + depPrefix + depTarget; - if (depExt.length() > 0) { - dependency += DOT + depExt; - } - managedProjectOutputs.add(dependency); - } - buffer.append(TAB + "-cd" + WHITESPACE + buildDir + WHITESPACE + LOGICAL_AND + WHITESPACE + "$(MAKE) " + depTargets + NEWLINE); //$NON-NLS-1$ //$NON-NLS-2$ - } - } - buffer.append(NEWLINE); - } - - /* - * Write out the target rule as: - * targ_.: $(OBJS) [ ... ] - * $(BUILD_TOOL) $(FLAGS) $(OUTPUT_FLAG) $@ $(OBJS) $(USER_OBJS) $(LIB_DEPS) - */ - buffer.append(outputPrefix + target); - if (extension.length() > 0) { - buffer.append(DOT + extension); - } - buffer.append(COLON + WHITESPACE + "$(OBJS)"); //$NON-NLS-1$ - Iterator iter = managedProjectOutputs.listIterator(); - while (iter.hasNext()) { - buffer.append(WHITESPACE + (String)iter.next()); - } - buffer.append(NEWLINE); - buffer.append(TAB + cmd + WHITESPACE + flags + WHITESPACE + outflag + WHITESPACE + "$@" + WHITESPACE + "$(OBJS) $(USER_OBJS) $(LIBS)"); //$NON-NLS-1$ //$NON-NLS-2$ - buffer.append(NEWLINE + NEWLINE); - - // Always add a clean target - buffer.append("clean:" + NEWLINE); //$NON-NLS-1$ - buffer.append(TAB + "-$(RM)" + WHITESPACE + "$(OBJS)" + WHITESPACE + outputPrefix + target); //$NON-NLS-1$ //$NON-NLS-2$ - if (extension.length() > 0) { - buffer.append(DOT + extension); - } - buffer.append(NEWLINE + NEWLINE); - - buffer.append(".PHONY: all clean deps" + NEWLINE + NEWLINE); //$NON-NLS-1$ - - buffer.append(COMMENT_SYMBOL + WHITESPACE + ManagedBuilderCorePlugin.getResourceString(DEP_INCL) + NEWLINE); - buffer.append("-include ${patsubst %, %/subdir.dep, $(SUBDIRS)}" + NEWLINE); //$NON-NLS-1$ - buffer.append(NEWLINE); - - // Include makefile.targets supplemental makefile - buffer.append("-include $(ROOT)" + SEPARATOR + MAKEFILE_TARGETS + NEWLINE); //$NON-NLS-1$ - - return buffer; - } - - /* (non-javadoc) - * - * @param relativePath - * @param buffer - * @param resource - */ - protected void addRule(String relativePath, StringBuffer buffer, IResource resource) { - String rule = null; - String cmd = null; - String buildFlags = null; - String inputExtension = null; - String outputExtension = null; - String outflag = null; - String outputPrefix = null; - - // Is there a special rule for this file - if (false) { - } - else { - // Get the extension of the resource - inputExtension = resource.getFileExtension(); - // ASk the build model what it will produce from this - outputExtension = info.getOutputExtension(inputExtension); - /* - * Create the pattern rule in the format - * /%.o: $(ROOT)//%.cpp - * $(CC) $(CFLAGS) $(OUTPUT_FLAG) $@ $< - * - * Note that CC CFLAGS and OUTPUT_FLAG 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 - * g++ -g -O2 -c -I/cygdrive/c/eclipse/workspace/Project/headers -o $@ $< - */ - rule = relativePath + WILDCARD + DOT + outputExtension + COLON + WHITESPACE + "$(ROOT)" + SEPARATOR + relativePath + WILDCARD + DOT + inputExtension; //$NON-NLS-1$ - } - - // Check if the rule is listed as something we already generated in the makefile - if (!getRuleList().contains(rule)) { - // Add it to the list - getRuleList().add(rule); - - // Add the rule and command to the makefile - buffer.append(rule + NEWLINE); - cmd = info.getToolForSource(inputExtension); - buildFlags = info.getFlagsForSource(inputExtension); - outflag = info.getOutputFlag(outputExtension); - outputPrefix = info.getOutputPrefix(outputExtension); - buffer.append(TAB + cmd + WHITESPACE + buildFlags + WHITESPACE + outflag + WHITESPACE + outputPrefix + "$@" + WHITESPACE + "$<" + NEWLINE + NEWLINE); //$NON-NLS-1$ //$NON-NLS-2$ - } - } - - /** - * 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 - */ - public void appendBuildSubdirectory(IResource resource) { - IContainer container = resource.getParent(); - if (!getSubdirList().contains(container)) { - getSubdirList().add(container); - } - - } - - /** - * 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 - */ - public void appendModifiedSubdirectory(IResource resource) { - IContainer container = resource.getParent(); - 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); - } - } - - /** - * Check whether the build has been cancelled. Cancellation requests - * propagated to the caller by throwing OperationCanceledException. - * - * @see org.eclipse.core.runtime.OperationCanceledException#OperationCanceledException() - */ - public void checkCancel() { - if (monitor != null && monitor.isCanceled()) { - throw new OperationCanceledException(); - } - } - - /** - * Clients call this method when an incremental rebuild is required. The argument - * contains a set of resource deltas that will be used to determine which - * subdirectories need a new makefile and dependency list (if any). - * - * @param delta - * @throws CoreException - */ - public void generateMakefiles(IResourceDelta delta) throws CoreException { - /* - * Let's do a sanity check right now. - * - * 1. This is an incremental build, so if the top-level directory is not - * there, then a rebuild is needed. - */ - IFolder folder = project.getFolder(info.getConfigurationName()); - if (!folder.exists()) { - regenerateMakefiles(); - return; - } - - // Visit the resources in the delta and compile a list of subdirectories to regenerate - ResourceDeltaVisitor visitor = new ResourceDeltaVisitor(this, info); - delta.accept(visitor); - - // See if the user has cancelled the build - checkCancel(); - - // The top-level makefile needs this information - ResourceProxyVisitor resourceVisitor = new ResourceProxyVisitor(this, info); - project.accept(resourceVisitor, IResource.NONE); - checkCancel(); - - // Regenerate any fragments that are missing for the exisiting directories NOT modified - Iterator iter = getSubdirList().listIterator(); - while (iter.hasNext()) { - IContainer subdirectory = (IContainer)iter.next(); - if (!getModifiedList().contains(subdirectory)) { - // Make sure a fragment makefile and dependency file exist - IFile makeFragment = project.getFile(subdirectory.getFullPath().addTrailingSeparator().append(MODFILE_NAME)); - IFile depFragment = project.getFile(subdirectory.getFullPath().addTrailingSeparator().append(DEPFILE_NAME)); - if (!makeFragment.exists() || !depFragment.exists()) { - // If one or both are missing, then add it to the list to be generated - getModifiedList().add(subdirectory); - } - } - } - - // Re-create the top-level makefile - topBuildDir = createDirectory(info.getConfigurationName()); - IPath makefilePath = topBuildDir.addTrailingSeparator().append(MAKEFILE_NAME); - IFile makefileHandle = createFile(makefilePath); - populateTopMakefile(makefileHandle, false); - checkCancel(); - - // Regenerate any fragments for modified directories - iter = getModifiedList().listIterator(); - while (iter.hasNext()) { - populateFragmentMakefile((IContainer) iter.next()); - checkCancel(); - } - } - - /* (non-javadoc) - * - * @return List - */ - private List getModifiedList() { - if (modifiedList == null) { - modifiedList = new ArrayList(); - } - return modifiedList; - } - - /* (non-javadoc) - * Answers the list of known build rules. This keeps me from generating duplicate - * rules for known file extensions. - * - * @return List - */ - private List getRuleList() { - if (ruleList == null) { - ruleList = new ArrayList(); - } - return ruleList; - } - - /* (non-javadoc) - * Answers the list of subdirectories contributing source code to the build - * - * @return List - */ - private List getSubdirList() { - if (subdirList == null) { - subdirList = new ArrayList(); - } - return subdirList; - } - - /* (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 - * @param monitor - * @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, monitor); - // 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; - } - - /** - * Answers the IPath of the top directory generated for the build - * output, or null if none has been generated. - * - * @return IPath - */ - public IPath getTopBuildDir() { - return topBuildDir; - } - - /** - * Answers true if the argument is found in a generated container - * @param resource - * @return boolean - */ - public boolean isGeneratedResource(IResource resource) { - // Is this a generated directory ... - IPath path = resource.getProjectRelativePath(); - String[] configNames = info.getConfigurationNames(); - for (int i = 0; i < configNames.length; i++) { - String name = configNames[i]; - IPath root = new Path(name); - // It is if it is a root of the resource pathname - if (root.isPrefixOf(path)) return true; - } - - return false; - } - - /* (non-javadoc) - * Create the entire contents of the makefile. - * - * @param fileHandle The file to place the contents in. - * @param rebuild FLag signalling that the user is doing a full rebuild - * @throws CoreException - */ - protected void populateTopMakefile(IFile fileHandle, boolean rebuild) throws CoreException { - StringBuffer buffer = new StringBuffer(); - - // Add the header - buffer.append(addTopHeader()); - - // Add the macro definitions - buffer.append(addMacros()); - - // Append the module list - buffer.append(addSubdirectories()); - - // Add targets - buffer.append(addTargets(rebuild)); - - // Save the file - Util.save(buffer, fileHandle); - } - - /* (non-javadoc) - * @param module - * @throws CoreException - */ - protected void populateFragmentMakefile(IContainer module) throws CoreException { - // Calcualte the new directory relative to the build output - IPath moduleRelativePath = module.getProjectRelativePath(); - IPath buildRoot = getTopBuildDir().removeFirstSegments(1); - if (buildRoot == null) { - return; - } - IPath moduleOutputPath = buildRoot.append(moduleRelativePath); - - // Now create the directory - IPath moduleOutputDir = createDirectory(moduleOutputPath.toString()); - - // Create a module makefile - IFile modMakefile = createFile(moduleOutputDir.addTrailingSeparator().append(MODFILE_NAME)); - StringBuffer makeBuf = new StringBuffer(); - makeBuf.append(addFragmentMakefileHeader()); - makeBuf.append(addSources(module)); - - // Create a module dep file - IFile modDepfile = createFile(moduleOutputDir.addTrailingSeparator().append(DEPFILE_NAME)); - StringBuffer depBuf = new StringBuffer(); - depBuf.append(addFragmentDependenciesHeader()); - depBuf.append(addSourceDependencies(module)); - - // Save the files - Util.save(makeBuf, modMakefile); - Util.save(depBuf, modDepfile); - } - - - /** - * @throws CoreException - */ - public void regenerateMakefiles() throws CoreException { - // 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()) { - return; - } - - // Create the top-level directory for the build output - topBuildDir = createDirectory(info.getConfigurationName()); - - // Create the top-level makefile - IPath makefilePath = topBuildDir.addTrailingSeparator().append(MAKEFILE_NAME); - IFile makefileHandle = createFile(makefilePath); - - populateTopMakefile(makefileHandle, true); - checkCancel(); - - // Now populate the module makefiles - ListIterator iter = getSubdirList().listIterator(); - while (iter.hasNext()) { - try { - populateFragmentMakefile((IContainer)iter.next()); - } catch (CoreException e) { - - } - checkCancel(); - } - } -} 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 497f3189054..0d4fc9b0311 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 @@ -17,6 +17,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Vector; import org.eclipse.cdt.core.CCProjectNature; import org.eclipse.cdt.core.CProjectNature; @@ -41,9 +42,12 @@ import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.QualifiedName; +import org.eclipse.core.runtime.jobs.Job; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; @@ -92,10 +96,26 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo { cModelElement = CoreModel.getDefault().create(owner.getProject()); try { - CoreModel.getDefault().setRawPathEntries(cModelElement, new IPathEntry[]{containerEntry}, new NullProgressMonitor()); - } catch (CModelException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); + IPathEntry[] entries = cModelElement.getRawPathEntries(); + if (entries.length > 0 && entries[0].equals(containerEntry)) { + + } else { + Job initJob = new Job("Initializing path container") { + protected IStatus run(IProgressMonitor monitor) { + try { + // Set the raw path entries + cModelElement.setRawPathEntries(new IPathEntry[]{containerEntry}, new NullProgressMonitor()); + } catch (CModelException e) { + ManagedBuilderCorePlugin.log(e); + } + return null; + } + + }; + initJob.schedule(); + } + } catch (CModelException e) { + ManagedBuilderCorePlugin.log(e); } isDirty = false; @@ -161,27 +181,11 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo { // Check to see if there is a rule to build a file with this extension IConfiguration config = getDefaultConfiguration(getDefaultTarget()); - ITool[] tools = config.getTools(); + ITool[] tools = config.getFilteredTools(project); 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.buildsFileType(srcExt); - } - break; - case ITool.FILTER_CC: - if (project.hasNature(CCProjectNature.CC_NATURE_ID)) { - return tool.buildsFileType(srcExt); - } - break; - case ITool.FILTER_BOTH: - return tool.buildsFileType(srcExt); - } - } catch (CoreException e) { - continue; + if (tool != null && tool.buildsFileType(srcExt)) { + return true; } } return false; @@ -365,31 +369,14 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo { // Get all the tools for the current config IConfiguration config = getDefaultConfiguration(getDefaultTarget()); - ITool[] tools = config.getTools(); + ITool[] tools = config.getFilteredTools(project); for (int index = 0; index < tools.length; index++) { ITool tool = tools[index]; - if (tool.buildsFileType(extension)) { + if (tool != null && tool.buildsFileType(extension)) { 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.getToolFlags(); - } - break; - case ITool.FILTER_CC: - if (project.hasNature(CCProjectNature.CC_NATURE_ID)) { - return tool.getToolFlags(); - } - break; - case ITool.FILTER_BOTH: - return tool.getToolFlags(); - } - } catch (CoreException e) { - continue; + return tool.getToolFlags(); } catch (BuildException e) { - // Give it your best shot with the next tool - continue; + return null; } } } @@ -406,31 +393,14 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo { // Get all the tools for the current config IConfiguration config = getDefaultConfiguration(getDefaultTarget()); - ITool[] tools = config.getTools(); + ITool[] tools = config.getFilteredTools(project); for (int index = 0; index < tools.length; index++) { ITool tool = tools[index]; if (tool.producesFileType(ext)) { 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.getToolFlags(); - } - break; - case ITool.FILTER_CC: - if (project.hasNature(CCProjectNature.CC_NATURE_ID)) { - return tool.getToolFlags(); - } - break; - case ITool.FILTER_BOTH: - return tool.getToolFlags(); - } - } catch (CoreException e) { - continue; + return tool.getToolFlags(); } catch (BuildException e) { - // Give it your best shot with the next tool - continue; + return null; } } } @@ -534,32 +504,12 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo { public String[] getLibsForTarget(String extension) { IProject project = (IProject)owner; - ArrayList libs = new ArrayList(); + Vector libs = new Vector(); // Get all the tools for the current config IConfiguration config = getDefaultConfiguration(getDefaultTarget()); - ITool[] tools = config.getTools(); + ITool[] tools = config.getFilteredTools(project); 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)) { - continue; - } - break; - case ITool.FILTER_CC: - if (!project.hasNature(CCProjectNature.CC_NATURE_ID)) { - continue; - } - break; - case ITool.FILTER_BOTH: - break; - } - } catch (CoreException e) { - continue; - } - // The tool is OK for this project nature if (tool.producesFileType(extension)) { IOption[] opts = tool.getOptions(); // Look for the lib option type @@ -580,7 +530,6 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo { } } } - libs.trimToSize(); return (String[])libs.toArray(new String[libs.size()]); } @@ -603,29 +552,16 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo { */ public String getOutputExtension(String resourceExtension) { IProject project = (IProject)owner; + String outputExtension = null; + // Get all the tools for the current config IConfiguration config = getDefaultConfiguration(getDefaultTarget()); - ITool[] tools = config.getTools(); + ITool[] tools = config.getFilteredTools(project); 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.getOutputExtension(resourceExtension); - } - break; - case ITool.FILTER_CC: - if (project.hasNature(CCProjectNature.CC_NATURE_ID)) { - return tool.getOutputExtension(resourceExtension); - } - break; - case ITool.FILTER_BOTH: - return tool.getOutputExtension(resourceExtension); - } - } catch (CoreException e) { - continue; + outputExtension = tool.getOutputExtension(resourceExtension); + if (outputExtension != null) { + return outputExtension; } } return null; @@ -642,28 +578,9 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo { // Get all the tools for the current config String flags = new String(); IConfiguration config = getDefaultConfiguration(getDefaultTarget()); - ITool[] tools = config.getTools(); + ITool[] tools = config.getFilteredTools(project); 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)) { - continue; - } - break; - case ITool.FILTER_CC: - if (!project.hasNature(CCProjectNature.CC_NATURE_ID)) { - continue; - } - break; - case ITool.FILTER_BOTH: - break; - } - } catch (CoreException e) { - continue; - } // It's OK if (tool.producesFileType(ext)) { flags = tool.getOutputFlag(); @@ -683,28 +600,9 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo { // Get all the tools for the current config String flags = new String(); IConfiguration config = getDefaultConfiguration(getDefaultTarget()); - ITool[] tools = config.getTools(); + ITool[] tools = config.getFilteredTools(project); 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)) { - continue; - } - break; - case ITool.FILTER_CC: - if (!project.hasNature(CCProjectNature.CC_NATURE_ID)) { - continue; - } - break; - case ITool.FILTER_BOTH: - break; - } - } catch (CoreException e) { - continue; - } if (tool.producesFileType(ext)) { flags = tool.getOutputPrefix(); } @@ -756,29 +654,11 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo { // Get all the tools for the current config IConfiguration config = getDefaultConfiguration(getDefaultTarget()); - ITool[] tools = config.getTools(); + ITool[] tools = config.getFilteredTools(project); for (int index = 0; index < tools.length; index++) { ITool tool = tools[index]; if (tool.buildsFileType(extension)) { - 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.getToolCommand(); - } - break; - case ITool.FILTER_CC: - if (project.hasNature(CCProjectNature.CC_NATURE_ID)) { - return tool.getToolCommand(); - } - break; - case ITool.FILTER_BOTH: - return tool.getToolCommand(); - } - } catch (CoreException e) { - continue; - } + return tool.getToolCommand(); } } return null; @@ -794,29 +674,11 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo { String ext = extension == null ? new String() : extension; // Get all the tools for the current config IConfiguration config = getDefaultConfiguration(getDefaultTarget()); - ITool[] tools = config.getTools(); + ITool[] tools = config.getFilteredTools(project); for (int index = 0; index < tools.length; index++) { ITool tool = tools[index]; if (tool.producesFileType(ext)) { - 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.getToolCommand(); - } - break; - case ITool.FILTER_CC: - if (project.hasNature(CCProjectNature.CC_NATURE_ID)) { - return tool.getToolCommand(); - } - break; - case ITool.FILTER_BOTH: - return tool.getToolCommand(); - } - } catch (CoreException e) { - continue; - } + return tool.getToolCommand(); } } return null; @@ -827,31 +689,12 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo { */ public String[] getUserObjectsForTarget(String extension) { IProject project = (IProject)owner; - ArrayList objs = new ArrayList(); + Vector objs = new Vector(); // Get all the tools for the current config IConfiguration config = getDefaultConfiguration(getDefaultTarget()); - ITool[] tools = config.getTools(); + ITool[] tools = config.getFilteredTools(project); 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)) { - continue; - } - break; - case ITool.FILTER_CC: - if (!project.hasNature(CCProjectNature.CC_NATURE_ID)) { - continue; - } - break; - case ITool.FILTER_BOTH: - break; - } - } catch (CoreException e) { - continue; - } // The tool is OK for this project nature if (tool.producesFileType(extension)) { IOption[] opts = tool.getOptions(); @@ -868,7 +711,6 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo { } } } - objs.trimToSize(); return (String[])objs.toArray(new String[objs.size()]); } @@ -985,8 +827,7 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo { IPathEntryContainer container = new ManagedBuildCPathEntryContainer(this); CoreModel.getDefault().setPathEntryContainer(new ICProject[]{cModelElement}, container, new NullProgressMonitor()); } catch (CModelException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + ManagedBuilderCorePlugin.log(e); } } @@ -1122,7 +963,7 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo { // And finally update the cModelElement cModelElement = CoreModel.getDefault().create(owner.getProject()); try { - CoreModel.getDefault().setRawPathEntries(cModelElement, new IPathEntry[]{containerEntry}, new NullProgressMonitor()); + CoreModel.setRawPathEntries(cModelElement, new IPathEntry[]{containerEntry}, new NullProgressMonitor()); } catch (CModelException e) { // TODO Auto-generated catch block e.printStackTrace(); diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ManagedMakeMessages.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ManagedMakeMessages.java new file mode 100644 index 00000000000..3314aee6ae8 --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ManagedMakeMessages.java @@ -0,0 +1,58 @@ +/********************************************************************** + * Copyright (c) 2004 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 + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.managedbuilder.internal.core; + +import java.text.MessageFormat; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +/** + * @since 2.0 + */ +public class ManagedMakeMessages { + // Bundle ID + private static final String BUNDLE_ID = "org.eclipse.cdt.managedbuilder.internal.core.PluginResources"; //$NON-NLS-1$ + //Resource bundle. + private static ResourceBundle resourceBundle; + + static { + try { + resourceBundle = ResourceBundle.getBundle(BUNDLE_ID); + } catch (MissingResourceException x) { + resourceBundle = null; + } + } + + public static String getResourceString(String key) { + try { + return resourceBundle.getString(key); + } catch (MissingResourceException e) { + return "!" + key + "!"; //$NON-NLS-1$ //$NON-NLS-2$ + } catch (NullPointerException e) { + return "#" + key + "#"; //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + public static String getFormattedString(String key, String arg) { + return MessageFormat.format(getResourceString(key), new String[] { arg }); + } + + public static String getFormattedString(String key, String[] args) { + return MessageFormat.format(getResourceString(key), args); + } + + /** + * + */ + private ManagedMakeMessages() { + // No constructor + } +} 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 8af8c8b85c5..1c7947f3ae0 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 @@ -25,7 +25,6 @@ import org.eclipse.cdt.managedbuilder.core.IOption; import org.eclipse.cdt.managedbuilder.core.IOptionCategory; import org.eclipse.cdt.managedbuilder.core.ITool; import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; -import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin; public class Option extends BuildObject implements IOption { // Static default return values @@ -230,7 +229,7 @@ public class Option extends BuildObject implements IOption { */ public String[] getDefinedSymbols() throws BuildException { if (valueType != PREPROCESSOR_SYMBOLS) { - throw new BuildException(ManagedBuilderCorePlugin.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ + throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } ArrayList v = (ArrayList)value; if (v == null) { @@ -315,7 +314,7 @@ public class Option extends BuildObject implements IOption { */ public String[] getIncludePaths() throws BuildException { if (valueType != INCLUDE_PATH) { - throw new BuildException(ManagedBuilderCorePlugin.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ + throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } ArrayList v = (ArrayList)value; if (v == null) { @@ -331,7 +330,7 @@ public class Option extends BuildObject implements IOption { */ public String[] getLibraries() throws BuildException { if (valueType != LIBRARIES) { - throw new BuildException(ManagedBuilderCorePlugin.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ + throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } ArrayList v = (ArrayList)value; if (v == null) { @@ -347,7 +346,7 @@ public class Option extends BuildObject implements IOption { */ public String getSelectedEnum() throws BuildException { if (valueType != ENUMERATED) { - throw new BuildException(ManagedBuilderCorePlugin.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ + throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } return defaultEnumId == null ? EMPTY_STRING : defaultEnumId; } @@ -357,7 +356,7 @@ public class Option extends BuildObject implements IOption { */ public String[] getStringListValue() throws BuildException { if (valueType != STRING_LIST) { - throw new BuildException(ManagedBuilderCorePlugin.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ + throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } ArrayList v = (ArrayList)value; if (v == null) { @@ -373,7 +372,7 @@ public class Option extends BuildObject implements IOption { */ public String getStringValue() throws BuildException { if (valueType != STRING) { - throw new BuildException(ManagedBuilderCorePlugin.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ + throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } return value == null ? EMPTY_STRING : (String)value; } @@ -390,7 +389,7 @@ public class Option extends BuildObject implements IOption { */ public String[] getUserObjects() throws BuildException { if (valueType != OBJECTS) { - throw new BuildException(ManagedBuilderCorePlugin.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ + throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } // This is the right puppy, so return its list value ArrayList v = (ArrayList)value; @@ -424,7 +423,7 @@ public class Option extends BuildObject implements IOption { { if (valueType != IOption.STRING || valueType != ENUMERATED) - throw new BuildException(ManagedBuilderCorePlugin.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ + throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ if (config == null) { this.value = value; @@ -446,7 +445,7 @@ public class Option extends BuildObject implements IOption { || valueType != PREPROCESSOR_SYMBOLS || valueType != LIBRARIES || valueType != OBJECTS) - throw new BuildException(ManagedBuilderCorePlugin.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ + throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ if (config == null) { this.value = value; diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/OptionReference.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/OptionReference.java index 4fc0e6e7d03..cb555795c8a 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/OptionReference.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/OptionReference.java @@ -21,7 +21,6 @@ import org.eclipse.cdt.managedbuilder.core.IOption; import org.eclipse.cdt.managedbuilder.core.IOptionCategory; import org.eclipse.cdt.managedbuilder.core.ITool; import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; -import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -281,7 +280,7 @@ public class OptionReference implements IOption { return (String[]) list.toArray(new String[list.size()]); } else - throw new BuildException(ManagedBuilderCorePlugin.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ + throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } /* (non-Javadoc) @@ -332,7 +331,7 @@ public class OptionReference implements IOption { return (String[]) list.toArray(new String[list.size()]); } else - throw new BuildException(ManagedBuilderCorePlugin.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ + throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } /* (non-Javadoc) @@ -346,7 +345,7 @@ public class OptionReference implements IOption { return (String[]) list.toArray(new String[list.size()]); } else - throw new BuildException(ManagedBuilderCorePlugin.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ + throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } /* (non-Javadoc) @@ -368,7 +367,7 @@ public class OptionReference implements IOption { Boolean bool = (Boolean) value; return bool.booleanValue(); } else { - throw new BuildException(ManagedBuilderCorePlugin.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ + throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } } @@ -430,7 +429,7 @@ public class OptionReference implements IOption { // This is a valid ID return (String) value; } else { - throw new BuildException(ManagedBuilderCorePlugin.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ + throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } } @@ -445,7 +444,7 @@ public class OptionReference implements IOption { return (String[]) list.toArray(new String[list.size()]); } else - throw new BuildException(ManagedBuilderCorePlugin.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ + throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } /* (non-Javadoc) @@ -457,7 +456,7 @@ public class OptionReference implements IOption { else if (getValueType() == STRING) return (String)value; else - throw new BuildException(ManagedBuilderCorePlugin.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ + throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } /* (non-Javadoc) @@ -487,7 +486,7 @@ public class OptionReference implements IOption { return (String[]) list.toArray(new String[list.size()]); } else - throw new BuildException(ManagedBuilderCorePlugin.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ + throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } /* (non-Javadoc) @@ -529,7 +528,7 @@ public class OptionReference implements IOption { if (getValueType() == BOOLEAN) this.value = new Boolean(value); else - throw new BuildException(ManagedBuilderCorePlugin.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ + throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } /** @@ -541,7 +540,7 @@ public class OptionReference implements IOption { if (getValueType() == STRING || getValueType() == ENUMERATED) { this.value = value; } else { - throw new BuildException(ManagedBuilderCorePlugin.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ + throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } } @@ -561,7 +560,7 @@ public class OptionReference implements IOption { this.value = new ArrayList(Arrays.asList(value)); } else - throw new BuildException(ManagedBuilderCorePlugin.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ + throw new BuildException(ManagedMakeMessages.getResourceString("Option.error.bad_value_type")); //$NON-NLS-1$ } /* (non-Javadoc) 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 6962600bfd7..45e8fedef66 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 @@ -20,13 +20,6 @@ ManagedMakeBuilder.message.console.header = **** {0} of configuration {1} for pr ManagedMakeBuilder.message.error = Build error ManagedMakeBuilder.message.error.refresh = Error refreshing project ManagedMakeBuilder.message.finished = Build complete for project {0} -ManagedMakeBuilder.comment.module.list = Every subdirectory with source files must be described here -ManagedMakeBuilder.comment.source.list = Each subdirectory must contribute its source files here -ManagedMakeBuilder.comment.build.rule = Each subdirectory must supply rules for building sources it contributes -ManagedMakeBuilder.comment.module.make.includes = Include the makefiles for each source subdirectory -ManagedMakeBuilder.comment.module.dep.includes = Include automatically-generated dependency list: -ManagedMakeBuilder.comment.autodeps = Automatically-generated dependency list: -ManagedMakeBuilder.comment.header = Automatically-generated file. Do not edit! ManagedMakeBuilder.type.full = Full rebuild ManagedMakeBuider.type.incremental = Incremental build @@ -39,3 +32,16 @@ ManagedBuildManager.error.null_owner=addTarget: null owner ManagedBuildManager.error.owner_not_project=addTarget: owner not project ManagedBuildManager.error.manifest.version.error=The version of plugin file is higher than version of the build system ManagedBuildManager.error.project.version.error=The version of the project is higher than the build system + +# 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.comment.module.list = Every subdirectory with source files must be described here +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.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! 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 de5f9b5736a..90ebf6fe19e 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 @@ -330,7 +330,10 @@ public class Target extends BuildObject implements ITarget { if (makeCommand != null) { element.setAttribute(MAKE_COMMAND, makeCommand); + } else { + // Make sure we use the default } + if (makeArguments != null) { element.setAttribute(MAKE_ARGS, makeArguments); } @@ -420,7 +423,7 @@ public class Target extends BuildObject implements ITarget { if (parent != null) { return parent.getMakeCommand(); } else { - // The user has forgotten to specify a command in the plugin manifets. + // The user has forgotten to specify a command in the plugin manifest return new String("make"); //$NON-NLS-1$ } } else { @@ -721,7 +724,7 @@ public class Target extends BuildObject implements ITarget { return defaultExtension; } } - + /* (non-Javadoc) * @see org.eclipse.cdt.managedbuilder.core.ITarget#getBinaryParserId() */ 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 26e7f3cae71..24859b1113b 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 @@ -180,12 +180,9 @@ public class Tool extends BuildObject implements ITool, IOptionCategory { } /* (non-Javadoc) - * Safe accessor method to retrieve the list of valid source extensions - * the receiver know how to build. - * - * @return List + * @see org.eclipse.cdt.managedbuilder.core.ITool#getInputExtensions() */ - private List getInputExtensions() { + public List getInputExtensions() { if (inputExtensions == null) { inputExtensions = new ArrayList(); } diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ToolReference.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ToolReference.java index 1a8c036c008..2838148b298 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ToolReference.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/ToolReference.java @@ -273,8 +273,15 @@ public class ToolReference implements IToolReference { public String getId() { return parent.getId(); } - - /* (non-Javadoc) + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.core.ITool#getInputExtensions() + */ + public List getInputExtensions() { + return getTool().getInputExtensions(); + } + + /* (non-Javadoc) * @see org.eclipse.cdt.managedbuilder.core.IBuildObject#getName() */ public String getName() { diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/scannerconfig/ManagedBuildCPathEntryContainer.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/scannerconfig/ManagedBuildCPathEntryContainer.java index 083f1dc9d86..af5d169c64a 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/scannerconfig/ManagedBuildCPathEntryContainer.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/scannerconfig/ManagedBuildCPathEntryContainer.java @@ -16,7 +16,6 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.Vector; import org.eclipse.cdt.core.model.CoreModel; @@ -32,7 +31,7 @@ import org.eclipse.cdt.managedbuilder.core.IConfiguration; import org.eclipse.cdt.managedbuilder.core.IOption; import org.eclipse.cdt.managedbuilder.core.ITarget; import org.eclipse.cdt.managedbuilder.core.ITool; -import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin; +import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.cdt.managedbuilder.internal.core.ManagedBuildInfo; import org.eclipse.cdt.managedbuilder.scannerconfig.IManagedScannerInfoCollector; import org.eclipse.core.resources.IProject; @@ -73,8 +72,7 @@ public class ManagedBuildCPathEntryContainer implements IPathEntryContainer { protected void addDefinedSymbols(Map definedSymbols) { // Add a new macro entry for each defined symbol - Set macros = definedSymbols.keySet(); - Iterator keyIter = macros.iterator(); + Iterator keyIter = definedSymbols.keySet().iterator(); while (keyIter.hasNext()) { boolean add = true; String macro = (String) keyIter.next(); @@ -191,7 +189,7 @@ public class ManagedBuildCPathEntryContainer implements IPathEntryContainer { /* (non-Javadoc) * @see org.eclipse.cdt.core.model.IPathEntryContainer#getPathEntries() */ - public synchronized IPathEntry[] getPathEntries() { + public IPathEntry[] getPathEntries() { // TODO figure out when I can skip this step if (entries.isEmpty()) { // Load the toolchain-spec'd collector @@ -207,7 +205,7 @@ public class ManagedBuildCPathEntryContainer implements IPathEntryContainer { } // See if we can load a dynamic resolver String baseTargetId = parent.getId(); - IManagedScannerInfoCollector collector = ManagedBuilderCorePlugin.getDefault().getScannerInfoCollector(baseTargetId); + IManagedScannerInfoCollector collector = ManagedBuildManager.getScannerInfoCollector(baseTargetId); if (collector != null) { collector.setProject(info.getOwner().getProject()); calculateEntriesDynamically((IProject)info.getOwner(), collector); @@ -239,4 +237,5 @@ public class ManagedBuildCPathEntryContainer implements IPathEntryContainer { public IPath getPath() { return new Path("org.eclipse.cdt.managedbuilder.MANAGED_CONTAINER"); //$NON-NLS-1$ } + } diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/IManagedBuilderDependencyCalculator.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/IManagedBuilderDependencyCalculator.java new file mode 100644 index 00000000000..b0e6e1026f0 --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/IManagedBuilderDependencyCalculator.java @@ -0,0 +1,28 @@ +/********************************************************************** + * Copyright (c) 2004 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 + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.managedbuilder.makegen; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; + +/** + * @since 2.0 + */ +public interface IManagedBuilderDependencyCalculator { + public int TYPE_NODEPS = 0; + public int TYPE_COMMAND = 1; + public int TYPE_INDEXER = 2; + public int TYPE_EXTERNAL = 3; + + public IResource[] findDependencies(IResource resource, IProject project); + public int getCalculatorType(); + public String getDependencyCommand(); +} 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 new file mode 100644 index 00000000000..7c2b4549fae --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/IManagedBuilderMakefileGenerator.java @@ -0,0 +1,72 @@ +/********************************************************************** + * Copyright (c) 2004 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 + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.managedbuilder.makegen; + +import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; + +/** + * @since 2.0 + */ +public interface IManagedBuilderMakefileGenerator { + /** + * @throws CoreException + */ + public void generateDependencies() throws CoreException; + + /** + * Clients call this method when an incremental rebuild is required. The argument + * contains a set of resource deltas that will be used to determine which + * subdirectories need a new makefile and dependency list (if any). + * + * @param delta + * @throws CoreException + */ + public void generateMakefiles(IResourceDelta delta) throws CoreException ; + + /** + * Answers the path of the top directory generated for the build + * output, or null if none has been generated. + * + * @return IPath to the working directory of the build + */ + public IPath getBuildWorkingDir(); + + /** + * Answers the name of the top-level makefile generated by the receiver. + * + * @return name of the makefile. + */ + public String getMakefileName(); + + /** + * @param project + * @param info + * @param monitor + */ + public void initialize(IProject project, IManagedBuildInfo info, IProgressMonitor monitor); + + /** + * @param force + * @throws CoreException + */ + public void regenerateDependencies(boolean force) throws CoreException; + + /** + * @throws CoreException + */ + public void regenerateMakefiles() throws CoreException; + +} diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/DefaultGCCDependencyCalculator.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/DefaultGCCDependencyCalculator.java new file mode 100644 index 00000000000..e049897b334 --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/DefaultGCCDependencyCalculator.java @@ -0,0 +1,43 @@ +/********************************************************************** + * Copyright (c) 2004 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 + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.managedbuilder.makegen.gnu; + +import org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderDependencyCalculator; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; + +/** + * @since 2.0 + */ +public class DefaultGCCDependencyCalculator implements IManagedBuilderDependencyCalculator { + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderDependencyCalculator#findDependencies(org.eclipse.core.resources.IResource) + */ + public IResource[] findDependencies(IResource resource, IProject project) { + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderDependencyCalculator#getCalculatorType() + */ + public int getCalculatorType() { + return TYPE_COMMAND; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderDependencyCalculator#getDependencyCommand() + */ + public String getDependencyCommand() { + // TODO Auto-generated method stub + return "$(CC) -M $(CC_FLAGS) $< > makefile.dep"; //$NON-NLS-1$ + } + +} diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/DefaultIndexerDependencyCalculator.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/DefaultIndexerDependencyCalculator.java new file mode 100644 index 00000000000..811b4dfe96c --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/DefaultIndexerDependencyCalculator.java @@ -0,0 +1,86 @@ +/********************************************************************** + * Copyright (c) 2004 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 + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM - Initial API and implementation + **********************************************************************/ +package org.eclipse.cdt.managedbuilder.makegen.gnu; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.search.ICSearchConstants; +import org.eclipse.cdt.core.search.ICSearchScope; +import org.eclipse.cdt.core.search.SearchEngine; +import org.eclipse.cdt.internal.core.search.PathCollector; +import org.eclipse.cdt.internal.core.search.PatternSearchJob; +import org.eclipse.cdt.internal.core.search.indexing.IndexManager; +import org.eclipse.cdt.internal.core.search.matching.CSearchPattern; +import org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderDependencyCalculator; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspaceRoot; + +/** + * @since 2.0 + */ +public class DefaultIndexerDependencyCalculator implements IManagedBuilderDependencyCalculator { + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderDependencyCalculator#findDependencies(org.eclipse.core.resources.IResource) + */ + public IResource[] findDependencies(IResource resource, IProject project) { + PathCollector pathCollector = new PathCollector(); + ICSearchScope scope = SearchEngine.createWorkspaceScope(); + CSearchPattern pattern = CSearchPattern.createPattern(resource.getLocation().toOSString(), ICSearchConstants.INCLUDE, ICSearchConstants.REFERENCES, ICSearchConstants.EXACT_MATCH, true); + IndexManager indexManager = CCorePlugin.getDefault().getCoreModel().getIndexManager(); + indexManager.performConcurrentJob( + new PatternSearchJob( + (CSearchPattern) pattern, + scope, + pathCollector, + indexManager), + ICSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, + null, null); + + // We will get back an array of resource names relative to the workspace + String[] deps = pathCollector.getPaths(); + + // Convert them to something useful + List depList = new ArrayList(); + IResource res = null; + IWorkspaceRoot root = null; + if (project != null) { + root = project.getWorkspace().getRoot(); + } + for (int index = 0; index < deps.length; ++index) { + res = root.findMember(deps[index]); + if (res != null) { + depList.add(res); + } + } + + return (IResource[]) depList.toArray(new IResource[depList.size()]); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderDependencyCalculator#getCalculatorType() + */ + public int getCalculatorType() { + // Tell the + return TYPE_INDEXER; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderDependencyCalculator#getDependencyCommand() + */ + public String getDependencyCommand() { + // There is no command + return null; + } +} 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 new file mode 100644 index 00000000000..337ce478c00 --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu/GnuMakefileGenerator.java @@ -0,0 +1,1302 @@ +package org.eclipse.cdt.managedbuilder.makegen.gnu; + +/********************************************************************** + * Copyright (c) 2003,2004 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation + * **********************************************************************/ + +import java.io.ByteArrayInputStream; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.Vector; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.internal.core.model.Util; +import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo; +import org.eclipse.cdt.managedbuilder.core.ITarget; +import org.eclipse.cdt.managedbuilder.core.ITool; +import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; +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.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceDeltaVisitor; +import org.eclipse.core.resources.IResourceProxy; +import org.eclipse.core.resources.IResourceProxyVisitor; +import org.eclipse.core.resources.IResourceStatus; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.SubProgressMonitor; + +/** + * This is a specialized makefile generator that takes advantage of the + * extensions present in Gnu Make. + * + * @since 1.2 + */ +public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator { + + // this is used to draw a "comment line" + private static final int COLS_PER_LINE = 80; + + // String constants for messages + private static final String MESSAGE = "ManagedMakeBuilder.message"; //$NON-NLS-1$ + protected static final String MESSAGE_FINISH_BUILD = ManagedMakeMessages.getResourceString("MakefileGenerator.message.finish.build"); //$NON-NLS-1$ + protected static final String MESSAGE_START_BUILD = ManagedMakeMessages.getResourceString("MakefileGenerator.message.start.build"); //$NON-NLS-1$ + protected static final String MESSAGE_FINISH_FILE = ManagedMakeMessages.getResourceString("MakefileGenerator.message.finish.file"); //$NON-NLS-1$ + protected static final String MESSAGE_START_FILE = ManagedMakeMessages.getResourceString("MakefileGenerator.message.start.file"); //$NON-NLS-1$ + private static final String BUILD_ERROR = MESSAGE + ".error"; //$NON-NLS-1$ + private static final String COMMENT = "MakefileGenerator.comment"; //$NON-NLS-1$ + private static final String HEADER = COMMENT + ".header"; //$NON-NLS-1$ + private static final String MOD_LIST = COMMENT + ".module.list"; //$NON-NLS-1$ + private static final String SRC_LISTS = COMMENT + ".source.list"; //$NON-NLS-1$ + private static final String MOD_RULES = COMMENT + ".build.rule"; //$NON-NLS-1$ + private static final String MOD_INCL = COMMENT + ".module.make.includes"; //$NON-NLS-1$ + private static final String DEP_INCL = COMMENT + ".module.dep.includes"; //$NON-NLS-1$ + private static final String AUTO_DEP = COMMENT + ".autodeps"; //$NON-NLS-1$ + + // String constants for makefile contents + protected static final String AT = "@"; //$NON-NLS-1$ + protected static final String COLON = ":"; //$NON-NLS-1$ + protected static final String DEP_EXT = "d"; //$NON-NLS-1$ + protected static final String DEPFILE_NAME = "subdir.dep"; //$NON-NLS-1$ + protected static final String DOT = "."; //$NON-NLS-1$ + protected static final String ECHO = "echo"; //$NON-NLS-1$ + protected static final String IN_MACRO = "$<"; //$NON-NLS-1$ + protected static final String NEWLINE = System.getProperty("line.separator"); //$NON-NLS-1$ + protected static final String LINEBREAK = "\\" + NEWLINE; //$NON-NLS-1$ + protected static final String LOGICAL_AND = "&&"; //$NON-NLS-1$ + protected static final String MAKEFILE_NAME = "makefile"; //$NON-NLS-1$ + protected static final String MODFILE_NAME = "subdir.mk"; //$NON-NLS-1$ + protected static final String OUT_MACRO = "$@"; //$NON-NLS-1$ + protected static final String ROOT = "$(ROOT)"; //$NON-NLS-1$ + protected static final String SRCSFILE_NAME = "sources.mk"; //$NON-NLS-1$ protected static final String MAKEFILE_TARGETS = "makefile.targets"; //$NON-NLS-1$ + protected static final String SEPARATOR = "/"; //$NON-NLS-1$ + protected static final String SINGLE_QUOTE = "'"; //$NON-NLS-1$ + protected static final String TAB = "\t"; //$NON-NLS-1$ + protected static final String WHITESPACE = " "; //$NON-NLS-1$ + protected static final String WILDCARD = "%"; //$NON-NLS-1$ + protected static final String COMMENT_SYMBOL = "#"; //$NON-NLS-1$ + protected static final String MAKEFILE_INIT = "makefile.init"; //$NON-NLS-1$ + protected static final String MAKEFILE_DEFS = "makefile.defs"; //$NON-NLS-1$ + protected static final String MAKEFILE_TARGETS = "makefile.targets"; //$NON-NLS-1$ protected static final String MAKEFILE_TARGETS = "makefile.targets"; //$NON-NLS-1$ + + // Local variables needed by generator + private String buildTargetName; + private Vector deletedFileList; + private String extension; + protected IManagedBuildInfo info; + protected Vector modifiedList; + protected IProgressMonitor monitor; + protected IProject project; + protected Vector ruleList; + protected Vector subdirList; + protected IPath topBuildDir; + + + + /** + * This class is used to recursively walk the project and determine which + * modules contribute buildable source files. + */ + protected class ResourceProxyVisitor implements IResourceProxyVisitor { + private GnuMakefileGenerator generator; + private IManagedBuildInfo info; + + /** + * Constructs a new resource proxy visitor to quickly visit project + * resources. + */ + public ResourceProxyVisitor(GnuMakefileGenerator generator, IManagedBuildInfo info) { + this.generator = generator; + this.info = info; + } + + /* (non-Javadoc) + * @see org.eclipse.core.resources.IResourceProxyVisitor#visit(org.eclipse.core.resources.IResourceProxy) + */ + public boolean visit(IResourceProxy proxy) throws CoreException { + // No point in proceeding, is there + if (generator == null) { + return false; + } + + // Is this a resource we should even consider + if (proxy.getType() == IResource.FILE) { + // Check extension to see if build model should build this file + IResource resource = proxy.requestResource(); + String ext = resource.getFileExtension(); + if (info.buildsFileType(ext)) { + if (!generator.isGeneratedResource(resource)) { + generator.appendBuildSubdirectory(resource); + } + } + return false; + } + + // Recurse into subdirectories + return true; + } + + } + + /** + * This class walks the delta supplied by the build system to determine + * what resources have been changed. The logic is very simple. If a + * buildable resource (non-header) has been added or removed, the directories + * in which they are located are "dirty" so the makefile fragments for them + * have to be regenerated. + *

+ * The actual dependencies are recalculated as a result of the build step + * itself. We are relying on make to do the right things when confronted + * with a dependency on a moved header file. That said, make will treat + * the missing header file in a dependency rule as a target it has to build + * unless told otherwise. These dummy targets are added to the makefile + * to avoid a missing target error. + */ + public class ResourceDeltaVisitor implements IResourceDeltaVisitor { + private GnuMakefileGenerator generator; + private IManagedBuildInfo info; + + /** + * The constructor + */ + public ResourceDeltaVisitor(GnuMakefileGenerator generator, IManagedBuildInfo info) { + this.generator = generator; + this.info = info; + } + + /* (non-Javadoc) + * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta) + */ + public boolean visit(IResourceDelta delta) throws CoreException { + // Should the visitor keep iterating in current directory + boolean keepLooking = false; + IResource resource = delta.getResource(); + + // What kind of resource change has occurred + if (resource.getType() == IResource.FILE) { + String ext = resource.getFileExtension(); + boolean moved = false; + switch (delta.getKind()) { + case IResourceDelta.ADDED: + if (!generator.isGeneratedResource(resource)) { + // This is a source file so just add its container + if (info.buildsFileType(ext)) { + generator.appendModifiedSubdirectory(resource); + } + } + break; + case IResourceDelta.REMOVED: + // we get this notification if a resource is moved too + if (!generator.isGeneratedResource(resource)) { + // This is a source file so just add its container + if (info.buildsFileType(ext)) { + generator.appendModifiedSubdirectory(resource); + generator.appendDeletedFile(resource); + } + } + break; + default: + keepLooking = true; + break; + } + } if (resource.getType() == IResource.PROJECT) { + // If there is a zero-length delta, something the project depends on has changed so just call make + IResourceDelta[] children = delta.getAffectedChildren(); + if (children != null && children.length > 0) { + keepLooking = true; + } + } else { + // If the resource is part of the generated directory structure don't recurse + if (!generator.isGeneratedResource(resource)) { + keepLooking = true; + } + } + + return keepLooking; + } + } + + public GnuMakefileGenerator() { + super(); + } + + /** + * @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(); + } + } + + /* (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) + * Answers a StringBuffer containing the comment(s) + * for the top-level makefile. + */ + protected StringBuffer addTopHeader() { + return addDefaultHeader(); + } + + /* (non-Javadoc) + * Answers a StringBuffer containing the comment(s) + * for a fragment makefile. + */ + protected StringBuffer addFragmentMakefileHeader() { + return addDefaultHeader(); + } + + /* (non-Javadoc) + * Answers a StringBuffer containing the comment(s) + * for a dependency makefile. + */ + protected StringBuffer addFragmentDependenciesHeader() { + return addDefaultHeader(); + } + + /* (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) + * Outputs a comment formatted as follows: + * ##### ....... ##### + * # + * ##### ....... ##### + */ + 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) + */ + 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 $(OBJS:%.o=%.d)" + 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) + * @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(); + // 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 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$ + + // get the target for this project + ITarget myTarget = info.getDefaultTarget(); + + // get the list of tools associated with our target + ITool toolArray[] = myTarget.getTools(); + + // 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 = getOutputExtentions(); + + // put in rules if the file type is not a generated file + for(int k = 0; k < toolArray.length; k++) { + List extensionsList = toolArray[k].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? + !outputExtensionsSet.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 + "," + 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(); + for (int i = 0; i < resources.length; i++) { + IResource resource = resources[i]; + if (resource.getType() == IResource.FILE) { + String ext = resource.getFileExtension(); + if (info.buildsFileType(ext)) { + // look for the extension in the map + StringBuffer bufferForExtension = new StringBuffer(); + bufferForExtension.append(extensionToRuleStringMap.get(ext).toString()); + if(bufferForExtension != null && + !outputExtensionsSet.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) + * Answers a StrinBuffer 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.getToolForTarget(extension); + String flags = info.getFlagsForTarget(extension); + String outflag = info.getOutputFlag(extension); + String outputPrefix = info.getOutputPrefix(extension); + String targets = rebuild ? "clean all" : "all"; //$NON-NLS-1$ //$NON-NLS-2$ + + // Get all the projects the build target depends on + IProject[] deps = null; + try { + deps = 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 .... + } + + // Write out the all target first in case someone just runs make + // all: targ_ [deps] + String defaultTarget = "all:"; //$NON-NLS-1$ + if (deps.length > 0) { + defaultTarget += WHITESPACE + "deps"; //$NON-NLS-1$ + } + 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(); + if (deps.length > 0) { + buffer.append("deps:" + NEWLINE); //$NON-NLS-1$ + if (deps != null) { + for (int i = 0; i < deps.length; i++) { + IProject dep = deps[i]; + 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.isDirty()) { + depTargets = "clean all"; //$NON-NLS-1$ + } + String dependency = buildDir + SEPARATOR + depPrefix + depTarget; + if (depExt.length() > 0) { + dependency += DOT + depExt; + } + managedProjectOutputs.add(dependency); + } + buffer.append(TAB + "-cd" + WHITESPACE + buildDir + WHITESPACE + LOGICAL_AND + WHITESPACE + "$(MAKE) " + depTargets + NEWLINE); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + buffer.append(NEWLINE); + } + + /* + * Write out the target rule as: + * targ_.: $(OBJS) [ ... ] + * @echo 'Building target: $@' + * $(BUILD_TOOL) $(FLAGS) $(OUTPUT_FLAG) $@ $(OBJS) $(USER_OBJS) $(LIB_DEPS) + * @echo 'Finished building: $@' + * @echo + */ + buffer.append(outputPrefix + buildTargetName); + if (extension.length() > 0) { + buffer.append(DOT + extension); + } + buffer.append(COLON + WHITESPACE + "$(OBJS)"); //$NON-NLS-1$ + Iterator iter = managedProjectOutputs.listIterator(); + while (iter.hasNext()) { + buffer.append(WHITESPACE + (String)iter.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 + TAB + AT + ECHO + NEWLINE + NEWLINE); + + // Always add a clean target + buffer.append("clean:" + NEWLINE); //$NON-NLS-1$ + buffer.append(TAB + "-$(RM)" + WHITESPACE + "$(OBJS)" + WHITESPACE + "$(OBJS:%.o=%.d)" + WHITESPACE + outputPrefix + buildTargetName); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS$-3 + if (extension.length() > 0) { + buffer.append(DOT + extension); + } + buffer.append(NEWLINE + NEWLINE); + + buffer.append(".PHONY: all clean deps" + NEWLINE + NEWLINE); //$NON-NLS-1$ + + // Include makefile.targets supplemental makefile + buffer.append("-include $(ROOT)" + SEPARATOR + MAKEFILE_TARGETS + NEWLINE); //$NON-NLS-1$ + + return buffer; + } + + /* (non-javadoc) + * Create the pattern rule in the format: + * /.: $(ROOT)//. + * @echo 'Building file: $<' + * @ $@ $< && \ + * echo -n '/.d /' >> /.d && \ + * -P -M -MG $< >> /.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/foo.o: $(ROOT)/source1/foo.cpp + * @echo 'Building file: $<' + * @ g++ -g -O2 -c -I/cygdrive/c/eclipse/workspace/Project/headers -o $@ $< && \ + * echo -n 'source1/foo.d source1/' >> source1/foo.d && \ + * g++ -P -M -MG -g -O2 -c -I/cygdrive/c/eclipse/workspace/Project/headers $< >> source1/foo.d + * @echo 'Finished building: $<' + * @echo + * + * @param relativePath + * @param buffer + * @param resource + */ + private void addRule(String relativePath, StringBuffer buffer, IResource resource) { + String buildFlags = null; + String resourceName = getFileName(resource); + String inputExtension = resource.getFileExtension(); + String cmd = info.getToolForSource(inputExtension); + String outputExtension = info.getOutputExtension(inputExtension); + String outflag = null; + String outputPrefix = null; + + // Add the rule and command to the makefile + String buildRule = relativePath + resourceName + DOT + outputExtension + COLON + WHITESPACE + ROOT + SEPARATOR + relativePath + resourceName + DOT + inputExtension; + buffer.append(buildRule + NEWLINE); + buffer.append(TAB + AT + ECHO + WHITESPACE + SINGLE_QUOTE + MESSAGE_START_FILE + WHITESPACE + IN_MACRO + SINGLE_QUOTE + NEWLINE); + buildFlags = info.getFlagsForSource(inputExtension); + outflag = info.getOutputFlag(outputExtension); + outputPrefix = info.getOutputPrefix(outputExtension); + + // The command to build + buffer.append(TAB + AT + ECHO + WHITESPACE + cmd + WHITESPACE + buildFlags + WHITESPACE + outflag + WHITESPACE + outputPrefix + OUT_MACRO + WHITESPACE + IN_MACRO + NEWLINE); + buffer.append(TAB + AT + cmd + WHITESPACE + buildFlags + WHITESPACE + outflag + WHITESPACE + outputPrefix + OUT_MACRO + WHITESPACE + IN_MACRO); + + // TODO determine if there are any deps to calculate + if (true) { + buffer.append(WHITESPACE + LOGICAL_AND + WHITESPACE + LINEBREAK); + // TODO get the dep rule out of the tool + String depRule = relativePath + resourceName + DOT + DEP_EXT; + buffer.append(TAB + ECHO + WHITESPACE + "-n" + WHITESPACE + SINGLE_QUOTE + depRule + WHITESPACE + relativePath + SINGLE_QUOTE + WHITESPACE + ">" + WHITESPACE + depRule + WHITESPACE + LOGICAL_AND + WHITESPACE + LINEBREAK); //$NON-NLS-1$ //$NON-NLS-2$ + buffer.append(TAB + cmd + WHITESPACE + "-MM -MG -MP -P -w" + WHITESPACE + buildFlags + WHITESPACE + IN_MACRO + WHITESPACE + ">>" + WHITESPACE + depRule); //$NON-NLS-1$ //$NON-NLS-2$ + } + + // 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 + TAB + AT + ECHO + NEWLINE + NEWLINE); + + // Make sure we add the resource to the list of objects created during the build + + } + + /** + * 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 (!getSubdirList().contains(container)) { + getSubdirList().add(container); + } + } + + /** + * 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 (!getModifiedList().contains(container)) { + getModifiedList().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); + } + + + /** + * @return + */ + private Vector getDeletedFileList() { + if (deletedFileList == null) { + deletedFileList = new Vector(); + } + return deletedFileList; + } + + /* (non-Javadoc) + * @param message + */ + protected void cancel(String message) { + if (monitor != null && !monitor.isCanceled()) { + throw new OperationCanceledException(message); + } + } + + /** + * 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) + * @see org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator#generateDependencies() + */ + public void generateDependencies() throws CoreException { + // A NOP for this generator + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator#generateMakefiles(org.eclipse.core.resources.IResourceDelta) + */ + public void generateMakefiles(IResourceDelta delta) throws CoreException { + /* + * Let's do a sanity check right now. + * + * 1. This is an incremental build, so if the top-level directory is not + * there, then a rebuild is needed. + */ + IFolder folder = project.getFolder(info.getConfigurationName()); + if (!folder.exists()) { + regenerateMakefiles(); + return; + } + + // Make sure the build directory is available + topBuildDir = createDirectory(info.getConfigurationName()); + checkCancel(); + + // Visit the resources in the delta and compile a list of subdirectories to regenerate + ResourceDeltaVisitor visitor = new ResourceDeltaVisitor(this, info); + delta.accept(visitor); + checkCancel(); + + // Get all the subdirectories participating in the build + ResourceProxyVisitor resourceVisitor = new ResourceProxyVisitor(this, info); + project.accept(resourceVisitor, IResource.NONE); + IPath srcsFilePath = topBuildDir.addTrailingSeparator().append(SRCSFILE_NAME); + IFile srcsFileHandle = createFile(srcsFilePath); + populateSourcesMakefile(srcsFileHandle); + checkCancel(); + + // If any header files have been moved we have to regenerate all the dep files + + + // Regenerate any fragments that are missing for the exisiting directories NOT modified + Iterator iter = getSubdirList().listIterator(); + while (iter.hasNext()) { + IContainer subdirectory = (IContainer)iter.next(); + if (!getModifiedList().contains(subdirectory)) { + // Make sure a fragment makefile exists + IPath fragmentPath = getBuildWorkingDir().append(subdirectory.getProjectRelativePath()).addTrailingSeparator().append(MODFILE_NAME); + IFile makeFragment = project.getFile(fragmentPath); + if (!makeFragment.exists()) { + // If one or both are missing, then add it to the list to be generated + getModifiedList().add(subdirectory); + } + } + } + + // Delete the old dependency files for any deleted resources + iter = getDeletedFileList().listIterator(); + while (iter.hasNext()) { + IResource deletedFile = (IResource)iter.next(); + deleteDepFile(deletedFile); + deleteBuildTarget(deletedFile); + } + + // Re-create the top-level makefile + IPath makefilePath = topBuildDir.addTrailingSeparator().append(MAKEFILE_NAME); + IFile makefileHandle = createFile(makefilePath); + populateTopMakefile(makefileHandle, false); + checkCancel(); + + // Regenerate any fragments for modified directories + iter = getModifiedList().listIterator(); + while (iter.hasNext()) { + IContainer subDir = (IContainer) iter.next(); + populateFragmentMakefile(subDir); + checkCancel(); + } + } + + /** + * 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; + } + + 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() + */ + public String getMakefileName() { + return new String(MAKEFILE_NAME); + } + + /* (non-javadoc) + * + * @return List + */ + private Vector getModifiedList() { + if (modifiedList == null) { + modifiedList = new Vector(); + } + return modifiedList; + } + + protected Set getOutputExtentions() { + // Get the target for this project + ITarget myTarget = info.getDefaultTarget(); + + // Get the list of tools associated with our target + ITool toolArray[] = myTarget.getTools(); + + // 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. + HashSet 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 k = 0; k < toolArray.length; k++) + { + String[] outputs = toolArray[k].getOutputExtensions(); + 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; + } + + /* (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(); + } + + /** + * @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); + 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 + ManagedBuilderCorePlugin.log(e); + } + } + } + + /** + * @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 + ManagedBuilderCorePlugin.log(e); + } + } + } + + /* (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, monitor); + // 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; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator#getTopBuildDir() + */ + public IPath getBuildWorkingDir() { + return topBuildDir.removeFirstSegments(1); + } + + /** + * Answers true if the argument is found in a generated container + * @param resource + * @return boolean + */ + protected boolean isGeneratedResource(IResource resource) { + // Is this a generated directory ... + IPath path = resource.getProjectRelativePath(); + String[] configNames = info.getConfigurationNames(); + for (int i = 0; i < configNames.length; i++) { + String name = configNames[i]; + IPath root = new Path(name); + // It is if it is a root of the resource pathname + if (root.isPrefixOf(path)) return true; + } + + return false; + } + + /* (non-javadoc) + * Create the entire contents of the makefile. + * + * @param fileHandle The file to place the contents in. + * @param rebuild FLag signalling that the user is doing a full rebuild + * @throws CoreException + */ + protected void populateTopMakefile(IFile fileHandle, boolean rebuild) throws CoreException { + StringBuffer buffer = new StringBuffer(); + + // Add the header + buffer.append(addTopHeader()); + + // Add the macro definitions + buffer.append(addMacros()); + + // Add targets + buffer.append(addTargets(rebuild)); + + // Save the file + Util.save(buffer, fileHandle); + } + + /* (non-javadoc) + * @param module + * @throws CoreException + */ + protected void populateFragmentMakefile(IContainer module) throws CoreException { + // Calcualte the new directory relative to the build output + IPath moduleRelativePath = module.getProjectRelativePath(); + IPath buildRoot = getBuildWorkingDir(); + if (buildRoot == null) { + return; + } + IPath moduleOutputPath = buildRoot.append(moduleRelativePath); + + // Now create the directory + IPath moduleOutputDir = createDirectory(moduleOutputPath.toString()); + + // Create a module makefile + IFile modMakefile = createFile(moduleOutputDir.addTrailingSeparator().append(MODFILE_NAME)); + StringBuffer makeBuf = new StringBuffer(); + makeBuf.append(addFragmentMakefileHeader()); + makeBuf.append(addSources(module)); + + // Save the files + Util.save(makeBuf, modMakefile); + } + + /** + * 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. + * + * @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$ + + // Add the libraries this project depends on + macroBuffer.append("LIBS := "); //$NON-NLS-1$ + String[] libs = info.getLibsForTarget(extension); + for (int i = 0; i < libs.length; i++) { + String string = libs[i]; + macroBuffer.append(LINEBREAK + string); + } + macroBuffer.append(NEWLINE); + + // Add the extra user-specified objects + macroBuffer.append("USER_OBJS := "); //$NON-NLS-1$ + String[] userObjs = info.getUserObjectsForTarget(extension); + for (int j = 0; j < userObjs.length; j++) { + String string = userObjs[j]; + macroBuffer.append(LINEBREAK + string); + } + macroBuffer.append(NEWLINE); + + // 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 + ITarget myTarget = info.getDefaultTarget(); + + // get the list of tools associated with our target + ITool toolArray[] = myTarget.getTools(); + + // get the set of output extensions for all tools + Set outputExtensionsSet = getOutputExtentions(); + + // set of input extensions for which rules have been created so far + HashSet handledInputExtensionsSet = 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. + for(int k = 0; k < toolArray.length; k++) { + List extensionsList = toolArray[k].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(!outputExtensionsSet.contains(extensionName) && !handledInputExtensionsSet.contains(extensionName)) { + handledInputExtensionsSet.add(extensionName); + StringBuffer macroName = getMacroName(extensionName); + + // create dependency rule of the form + // OBJS = $(macroName1: $(ROOT)/%.input1=%.output1) ... $(macroNameN: $(ROOT)/%.inputN=%.outputN) + objectsBuffer.append(WHITESPACE + "$(" + macroName + COLON + "$(ROOT)" + SEPARATOR + WILDCARD + + DOT + extensionName + "=" + WILDCARD + DOT + + toolArray[k].getOutputExtension(extensionName) + ")" ); + } + } + } + + macroBuffer.append(NEWLINE + NEWLINE + objectsBuffer); + + // For now, just save the buffer that was populated when the rules were created + Util.save(macroBuffer, fileHandle); + } + + /** + * @param fileHandle + * @throws CoreException + */ + protected void populateSourcesMakefile(IFile fileHandle) throws CoreException { + // Add the comment + StringBuffer buffer = addDefaultHeader(); + + // Add the known macros + ITarget myTarget = info.getDefaultTarget(); + ITool toolArray[] = myTarget.getTools(); + Set outputExtensionsSet = getOutputExtentions(); + HashSet handledInputExtensionsSet = new HashSet(); + for(int k = 0; k < toolArray.length; k++) { + List extensionsList = toolArray[k].getInputExtensions(); + Iterator exListIterator = extensionsList.iterator(); + while(exListIterator.hasNext()) { + // create a macro of the form "EXTENSION_SRCS :=" + String extensionName = exListIterator.next().toString(); + if(!outputExtensionsSet.contains(extensionName) && !handledInputExtensionsSet.contains(extensionName)) { + handledInputExtensionsSet.add(extensionName); + StringBuffer macroName = getMacroName(extensionName); + buffer.append(macroName + WHITESPACE + ":=" + WHITESPACE + NEWLINE); + } + } + } + + // Add a list of subdirectories + buffer.append(NEWLINE + addSubdirectories()); + + // Save the file + Util.save(buffer, fileHandle); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator#regenerateDependencies() + */ + public void regenerateDependencies(boolean force) throws CoreException { + // A hack for the pre-3.x GCC compilers is to put dummy targets for deps + + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.managedbuilder.makegen.IManagedBuilderMakefileGenerator#regenerateMakefiles() + */ + public void regenerateMakefiles() throws CoreException { + // 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()) { + return; + } + + // 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(); + } + + // 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.mk"); + IFile objsFileHandle = createFile(objFilePath); + populateObjectsMakefile(objsFileHandle); + checkCancel(); + } + +} diff --git a/build/org.eclipse.cdt.managedbuilder.ui/plugin.xml b/build/org.eclipse.cdt.managedbuilder.ui/plugin.xml index cdd29efcbe5..942eedaaa27 100644 --- a/build/org.eclipse.cdt.managedbuilder.ui/plugin.xml +++ b/build/org.eclipse.cdt.managedbuilder.ui/plugin.xml @@ -848,13 +848,14 @@ + id="cdt.managedbuild.target.gnu.exe" + parent="cdt.managedbuild.target.gnu"> @@ -918,6 +919,7 @@ isTest="false" osList="solaris,linux,hpux,aix,macosx,qnx" scannerInfoCollector="org.eclipse.cdt.managedbuilder.internal.scannerconfig.DefaultGCCScannerInfoCollector" + makefileGenerator="org.eclipse.cdt.managedbuilder.makegen.gnu.GnuMakefileGenerator" name="%TargetName.gnu.so" parent="cdt.managedbuild.target.gnu" defaultExtension="so" @@ -990,6 +992,7 @@ isTest="false" osList="solaris,linux,hpux,aix,macosx,qnx" scannerInfoCollector="org.eclipse.cdt.managedbuilder.internal.scannerconfig.DefaultGCCScannerInfoCollector" + makefileGenerator="org.eclipse.cdt.managedbuilder.makegen.gnu.GnuMakefileGenerator" name="%TargetName.gnu.lib" parent="cdt.managedbuild.target.gnu" defaultExtension="a" @@ -1059,6 +1062,7 @@ isTest="false" defaultExtension="exe" scannerInfoCollector="org.eclipse.cdt.managedbuilder.internal.scannerconfig.DefaultCygwinScannerInfoCollector" + makefileGenerator="org.eclipse.cdt.managedbuilder.makegen.gnu.GnuMakefileGenerator" isAbstract="false" binaryParser="org.eclipse.cdt.core.PE" parent="cdt.managedbuild.target.gnu" @@ -1130,6 +1134,7 @@ isTest="false" defaultExtension="a.dll" scannerInfoCollector="org.eclipse.cdt.managedbuilder.internal.scannerconfig.DefaultCygwinScannerInfoCollector" + makefileGenerator="org.eclipse.cdt.managedbuilder.makegen.gnu.GnuMakefileGenerator" isAbstract="false" binaryParser="org.eclipse.cdt.core.PE" parent="cdt.managedbuild.target.gnu" @@ -1199,6 +1204,7 @@ name="%TargetName.cygw.lib" id="cdt.managedbuild.target.gnu.cygwin.lib" isTest="false" + makefileGenerator="org.eclipse.cdt.managedbuilder.makegen.gnu.GnuMakefileGenerator" defaultExtension="a" scannerInfoCollector="org.eclipse.cdt.managedbuilder.internal.scannerconfig.DefaultCygwinScannerInfoCollector" isAbstract="false" @@ -1269,6 +1275,7 @@ osList="win32" makeCommand="mingw32-make" scannerInfoCollector="org.eclipse.cdt.managedbuilder.internal.scannerconfig.DefaultMinGWScannerInfoCollector" + makefileGenerator="org.eclipse.cdt.managedbuilder.makegen.gnu.GnuMakefileGenerator" isTest="false" binaryParser="org.eclipse.cdt.core.PE" name="%TargetName.mingw.exe" @@ -1344,6 +1351,7 @@ scannerInfoCollector="org.eclipse.cdt.managedbuilder.internal.scannerconfig.DefaultMinGWScannerInfoCollector" isTest="false" binaryParser="org.eclipse.cdt.core.PE" + makefileGenerator="org.eclipse.cdt.managedbuilder.makegen.gnu.GnuMakefileGenerator" name="%TargetName.mingw.so" parent="cdt.managedbuild.target.gnu" id="cdt.managedbuild.target.gnu.mingw.so" @@ -1414,6 +1422,7 @@ defaultExtension="lib" osList="win32" makeCommand="mingw32-make" + makefileGenerator="org.eclipse.cdt.managedbuilder.ui.properties.BrowseEntryDialog" scannerInfoCollector="org.eclipse.cdt.managedbuilder.internal.scannerconfig.DefaultMinGWScannerInfoCollector" isTest="false" binaryParser="org.eclipse.cdt.core.PE"