diff options
Diffstat (limited to 'build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/MakefileGenerator.java')
-rw-r--r-- | build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/MakefileGenerator.java | 968 |
1 files changed, 0 insertions, 968 deletions
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 aadd19e8233..00000000000 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/MakefileGenerator.java +++ /dev/null @@ -1,968 +0,0 @@ -package org.eclipse.cdt.managedbuilder.internal.core; - -/********************************************************************** - * Copyright (c) 2002,2003 Rational Software Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v0.5 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v05.html - * - * Contributors: - * IBM Rational Software - Initial API and implementation - * **********************************************************************/ - -import java.io.ByteArrayInputStream; -import java.util.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 { - // 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 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 = ":"; - protected static final String DEPFILE_NAME = "subdir.dep"; //$NON-NLS-1$ - protected static final String DOT = "."; - 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 = "\\"; - protected static final String NEWLINE = System.getProperty("line.separator"); - protected static final String LOGICAL_AND = "&&"; - protected static final String SEPARATOR = "/"; - protected static final String TAB = "\t"; - protected static final String WHITESPACE = " "; - protected static final String WILDCARD = "%"; - - // 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 = (new Path(target)).getFileExtension(); - 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; - - // Create the buffer to hold the output for the module and a dep calculator - StringBuffer buffer = new StringBuffer(); - buffer.append(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 - * <relativePath>/<resourceName>.<outputExtension> : <dep1> ... <depn> - * 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 path = (String)iter.next(); - buffer.append(path + WHITESPACE); - } - 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); - - // Get the clean command from the build model - buffer.append("RM := "); - buffer.append(info.getCleanCommand() + NEWLINE + NEWLINE); - - buffer.append(ManagedBuilderCorePlugin.getResourceString(SRC_LISTS) + NEWLINE); - buffer.append("C_SRCS := " + NEWLINE); - buffer.append("CC_SRCS := " + NEWLINE); - buffer.append("CXX_SRCS := " + NEWLINE); - buffer.append("CAPC_SRCS := " + NEWLINE); - buffer.append("CPP_SRCS := " + NEWLINE + NEWLINE); - - // Add the libraries this project depends on - buffer.append("LIBS := "); - 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 := "); - 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); - return (buffer.append(NEWLINE)); - } - - /* (non-javadoc) - * @return - */ - protected StringBuffer addSubdirectories() { - StringBuffer buffer = new StringBuffer(); - // Add the comment - buffer.append(ManagedBuilderCorePlugin.getResourceString(MOD_LIST) + NEWLINE); - buffer.append("SUBDIRS := " + LINEBREAK + NEWLINE); - - // 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("." + 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(ManagedBuilderCorePlugin.getResourceString(MOD_INCL) + NEWLINE); - buffer.append("-include ${patsubst %, %/subdir.mk, $(SUBDIRS)}" + NEWLINE); - - buffer.append(NEWLINE + NEWLINE); - return buffer; - } - - - /* (non-javadoc) - * Answers a <code>StringBuffer</code> 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; - - // String buffers - StringBuffer buffer = new StringBuffer(); - StringBuffer cBuffer = new StringBuffer("C_SRCS += " + LINEBREAK + NEWLINE); - cBuffer.append("${addprefix $(ROOT)/" + relativePath + "," + LINEBREAK + NEWLINE); - StringBuffer ccBuffer = new StringBuffer("CC_SRCS += \\" + NEWLINE); - ccBuffer.append("${addprefix $(ROOT)/" + relativePath + "," + LINEBREAK + NEWLINE); - StringBuffer cxxBuffer = new StringBuffer("CXX_SRCS += \\" + NEWLINE); - cxxBuffer.append("${addprefix $(ROOT)/" + relativePath + "," + LINEBREAK + NEWLINE); - StringBuffer capcBuffer = new StringBuffer("CAPC_SRCS += \\" + NEWLINE); - capcBuffer.append("${addprefix $(ROOT)/" + relativePath + "," + LINEBREAK + NEWLINE); - StringBuffer cppBuffer = new StringBuffer("CPP_SRCS += \\" + NEWLINE); - cppBuffer.append("${addprefix $(ROOT)/" + relativePath + "," + LINEBREAK + NEWLINE); - StringBuffer ruleBuffer = new StringBuffer(ManagedBuilderCorePlugin.getResourceString(MOD_RULES) + NEWLINE); - - // Put the comment in - buffer.append(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)) { - cBuffer.append(resource.getName() + WHITESPACE + LINEBREAK + NEWLINE); - } else if (new String("cc").equalsIgnoreCase(ext)) { - ccBuffer.append(resource.getName() + WHITESPACE + LINEBREAK + NEWLINE); - } else if (new String("cxx").equalsIgnoreCase(ext)) { - cxxBuffer.append(resource.getName() + WHITESPACE + LINEBREAK + NEWLINE); - } else if (new String("C").equals(ext)) { - 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)); - buffer.append(ccBuffer.append("}" + NEWLINE + NEWLINE)); - buffer.append(cxxBuffer.append("}" + NEWLINE + NEWLINE)); - buffer.append(capcBuffer.append("}" + NEWLINE + NEWLINE)); - buffer.append(cppBuffer.append("}" + NEWLINE + NEWLINE)); - - return buffer.append(ruleBuffer + NEWLINE); - } - - /* (non-javadoc) - * Answers a <code>StrinBuffer</code> 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"; - - // 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_<target_name> [deps] - String defaultTarget = "all:"; - if (deps.length > 0) { - defaultTarget += WHITESPACE + "deps"; - } - buffer.append(defaultTarget + WHITESPACE + outputPrefix + target + NEWLINE); - buffer.append(NEWLINE); - - /* - * The build target may depend on other projects in the workspace. These are - * captured in the deps target: - * deps: - * <cd <Proj_Dep_1/build_dir>; $(MAKE) [clean all | all]> - */ - List managedProjectOutputs = new ArrayList(); - if (deps.length > 0) { - buffer.append("deps:" + NEWLINE); - 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 = (new Path(depTarget)).getFileExtension(); - String depPrefix = depInfo.getOutputPrefix(depExt); - if (depInfo.isDirty()) { - depTargets = "clean all"; - } - managedProjectOutputs.add(buildDir + SEPARATOR + depPrefix + depTarget); - } - buffer.append(TAB + "-cd" + WHITESPACE + buildDir + WHITESPACE + LOGICAL_AND + WHITESPACE + "$(MAKE) " + depTargets + NEWLINE); - } - } - buffer.append(NEWLINE); - } - - /* - * Write out the target rule as: - * targ_<prefix><target>.<extension>: $(OBJS) [<dep_proj_1_output> ... <dep_proj_n_output>] - * $(BUILD_TOOL) $(FLAGS) $(OUTPUT_FLAG) $@ $(OBJS) $(USER_OBJS) $(LIB_DEPS) - */ - buffer.append(outputPrefix + target + COLON + WHITESPACE + "$(OBJS)"); - 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)"); - buffer.append(NEWLINE + NEWLINE); - - // Always add a clean target - buffer.append("clean:" + NEWLINE); - buffer.append(TAB + "-$(RM)" + WHITESPACE + "$(OBJS)" + WHITESPACE + outputPrefix + target + NEWLINE + NEWLINE); - - buffer.append(".PHONY: all clean deps" + NEWLINE + NEWLINE); - - buffer.append(ManagedBuilderCorePlugin.getResourceString(DEP_INCL) + NEWLINE); - buffer.append("-include ${patsubst %, %/subdir.dep, $(SUBDIRS)}" + NEWLINE); - 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 - * <relative_path>/%.o: $(ROOT)/<relative_path>/%.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; - } - - // 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); - } - } - - /** - * 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); - } - } - - /** - * Check whether the build has been cancelled. Cancellation requests - * propagated to the caller by throwing <code>OperationCanceledException</code>. - * - * @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) - * @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; - } - } - return folder.getFullPath(); - } - - /* (non-javadoc) - * @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); - } - 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 <code>IPath</code> of the top directory generated for the build - * output, or <code>null</code> if none has been generated. - * - * @return IPath - */ - public IPath getTopBuildDir() { - return topBuildDir; - } - - /** - * Answers <code>true</code> 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 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(addSources(module)); - - // Create a module dep file - IFile modDepfile = createFile(moduleOutputDir.addTrailingSeparator().append(DEPFILE_NAME)); - StringBuffer depBuf = new StringBuffer(); - 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()) { - populateFragmentMakefile((IContainer)iter.next()); - checkCancel(); - } - } -} |