1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Patch for Sean Evoy:

- Initial makefile generator for managed build.
This commit is contained in:
Doug Schaefer 2003-07-25 14:40:04 +00:00
parent 196aedf345
commit 2ea02e1982
8 changed files with 1084 additions and 188 deletions

View file

@ -18,6 +18,7 @@ import junit.framework.TestSuite;
import junit.textui.TestRunner;
import org.eclipse.cdt.core.build.managed.tests.AllBuildTests;
import org.eclipse.cdt.core.build.managed.tests.StandardBuildTests;
import org.eclipse.cdt.core.model.failedTests.CModelElementsFailedTests;
import org.eclipse.cdt.core.model.tests.AllCoreTests;
import org.eclipse.cdt.core.model.tests.BinaryTests;
@ -77,6 +78,7 @@ public class AutomatedIntegrationSuite extends TestSuite
// Add all success tests
suite.addTest(AllBuildTests.suite());
suite.addTest(StandardBuildTests.suite());
suite.addTest(ParserTestSuite.suite());
suite.addTest(AllCoreTests.suite());
suite.addTest(BinaryTests.suite());

View file

@ -22,6 +22,15 @@ public interface IManagedBuildInfo {
*/
public void addTarget(ITarget target);
/**
* Answers <code>true</code> if the build system knows how to
* build a file with the extension passed in the argument.
*
* @param srcExt
* @return
*/
public boolean buildsFileType(String srcExt);
/**
* Returns the name of the artifact to build for the receiver.
*
@ -29,6 +38,21 @@ public interface IManagedBuildInfo {
*/
public String getBuildArtifactName();
/**
* Answers the command needed to remove files on the build machine
*
* @return
*/
public String getCleanCommand();
/**
* Answers the name of the default configuration, for example <code>Debug</code>
* or <code>Release</code>.
*
* @return
*/
public String getConfigurationName();
/**
* Get the default configuration associated with the receiver
*
@ -53,6 +77,16 @@ public interface IManagedBuildInfo {
*/
public String getOutputExtension(String resourceExtension);
/**
* Answers the flag to be passed to the build tool to produce a specific output
* or an empty <code>String</code> if there is no special flag. For example, the
* GCC tools use the -o flag to produce a named output, for example
* gcc -c foo.c -o foo.o
*
* @return
*/
public String getOutputFlag();
/**
* Get the target specified in the argument.
*
@ -88,6 +122,21 @@ public interface IManagedBuildInfo {
*/
public String getFlagsForTarget(String extension);
/**
* Answers a string array containing the arguments to be passed to
* make. For example, if the user has selected a build that stops
* at the first error, the array would contain {"k"}.
*
* @return
*/
public String[] getMakeArguments();
/**
* Answers a <code>String</code> containing the make command invocation
* for the default target/configuration.
*/
public String getMakeCommand();
/**
* Returns a <code>String</code> containing the command-line invocation
* for the tool associated with the source extension.
@ -121,4 +170,6 @@ public interface IManagedBuildInfo {
*/
public void setDefaultTarget(ITarget target);
}

View file

@ -328,25 +328,6 @@ public class ManagedBuildManager implements IScannerInfoProvider {
getExtensionTargetMap().put(target.getId(), target);
}
private static void loadExtensions() {
if (extensionTargetsLoaded)
return;
extensionTargetsLoaded = true;
IExtensionPoint extensionPoint = CCorePlugin.getDefault().getDescriptor().getExtensionPoint("ManagedBuildInfo");
IExtension[] extensions = extensionPoint.getExtensions();
for (int i = 0; i < extensions.length; ++i) {
IExtension extension = extensions[i];
IConfigurationElement[] elements = extension.getConfigurationElements();
for (int j = 0; j < elements.length; ++j) {
IConfigurationElement element = elements[j];
if (element.getName().equals("target")) {
new Target(element);
}
}
}
}
private static ManagedBuildInfo loadBuildInfo(IProject project) {
ManagedBuildInfo buildInfo = null;
IFile file = project.getFile(FILE_NAME);
@ -369,6 +350,58 @@ public class ManagedBuildManager implements IScannerInfoProvider {
return buildInfo;
}
private static void loadExtensions() {
if (extensionTargetsLoaded)
return;
extensionTargetsLoaded = true;
IExtensionPoint extensionPoint = CCorePlugin.getDefault().getDescriptor().getExtensionPoint("ManagedBuildInfo");
IExtension[] extensions = extensionPoint.getExtensions();
for (int i = 0; i < extensions.length; ++i) {
IExtension extension = extensions[i];
IConfigurationElement[] elements = extension.getConfigurationElements();
for (int j = 0; j < elements.length; ++j) {
IConfigurationElement element = elements[j];
if (element.getName().equals("target")) {
new Target(element);
}
}
}
}
/**
* @param project
* @return
*/
public static boolean manages(IResource resource) {
// The managed build manager manages build information for the
// resource IFF it it is a project and has a build file with the proper
// root element
IProject project = null;
if (resource instanceof IProject){
project = (IProject)resource;
} else if (resource instanceof IFile) {
project = ((IFile)resource).getProject();
} else {
return false;
}
IFile file = project.getFile(FILE_NAME);
if (file.exists()) {
try {
InputStream stream = file.getContents();
DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = parser.parse(stream);
Node rootElement = document.getFirstChild();
if (rootElement.getNodeName().equals(ROOT_ELEM_NAME)) {
return true;
}
} catch (Exception e) {
return false;
}
}
return false;
}
private static ManagedBuildInfo findBuildInfo(IResource resource, boolean create) {
// Make sure the extension information is loaded first
loadExtensions();
@ -417,6 +450,11 @@ public class ManagedBuildManager implements IScannerInfoProvider {
* Answers with an interface to the parse information that has been
* associated with the resource specified in the argument.
*
* NOTE: This method is not part of the registration interface. It has
* been made public as a short-term workaround for the clients of the
* scanner information until the redesign of the build information management
* occurs.
*
* @param resource
* @return
*/
@ -450,6 +488,9 @@ public class ManagedBuildManager implements IScannerInfoProvider {
}
}
// TODO Remove all of the IScannerInfoProvider interface methods when
// the discovery mechanism is solidified
/* (non-Javadoc)
* @see org.eclipse.cdt.core.parser.IScannerInfoProvider#managesResource(org.eclipse.core.resources.IResource)
*/
@ -504,4 +545,5 @@ public class ManagedBuildManager implements IScannerInfoProvider {
}
}
}

View file

@ -87,6 +87,22 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo {
targets.add(target);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.build.managed.IManagedBuildInfo#buildsFileType(java.lang.String)
*/
public boolean buildsFileType(String srcExt) {
// Check to see if there is a rule to build a file with this extension
IConfiguration config = getDefaultConfiguration(getDefaultTarget());
ITool[] tools = config.getTools();
for (int index = 0; index < tools.length; index++) {
ITool tool = tools[index];
if (tool.buildsFileType(srcExt)) {
return true;
}
}
return false;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#getBuildArtifactName()
*/
@ -96,6 +112,23 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo {
return name == null ? new String() : name;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.build.managed.IManagedBuildInfo#getCleanCommand()
*/
public String getCleanCommand() {
// TODO Get from the model
return new String("rm -rf");
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.build.managed.IManagedBuildInfo#getConfigurationName()
*/
public String getConfigurationName() {
// Return the human-readable name of the default configuration
IConfiguration config = getDefaultConfiguration(getDefaultTarget());
return config == null ? new String() : config.getName();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#getDefaultConfiguration()
*/
@ -168,6 +201,51 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo {
return null;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.build.managed.IScannerInfo#getIncludePaths()
*/
public String[] getIncludePaths() {
// Return the include paths for the default configuration
ArrayList paths = new ArrayList();
IConfiguration config = getDefaultConfiguration(getDefaultTarget());
ITool[] tools = config.getTools();
for (int i = 0; i < tools.length; i++) {
ITool tool = tools[i];
IOption[] opts = tool.getOptions();
for (int j = 0; j < opts.length; j++) {
IOption option = opts[j];
if (option.getValueType() == IOption.INCLUDE_PATH) {
try {
paths.addAll(Arrays.asList(option.getIncludePaths()));
} catch (BuildException e) {
// we should never get here
continue;
}
}
}
}
paths.trimToSize();
return (String[])paths.toArray(new String[paths.size()]);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.build.managed.IManagedBuildInfo#getMakeArguments()
*/
public String[] getMakeArguments() {
// TODO Stop hard-coding this
String[] args = {""};
return args;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.build.managed.IManagedBuildInfo#getMakeCommand()
*/
public String getMakeCommand() {
// TODO Don't hard-code this
return new String("make");
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#getOutputExtension(java.lang.String)
*/
@ -185,6 +263,15 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo {
return null;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.build.managed.IManagedBuildInfo#getOutputFlag()
*/
public String getOutputFlag() {
// TODO Stop hard-coding this
String flag = new String("-o");
return flag;
}
public IResource getOwner() {
return owner;
}
@ -319,31 +406,5 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo {
return symbols;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.build.managed.IScannerInfo#getIncludePaths()
*/
public String[] getIncludePaths() {
// Return the include paths for the default configuration
ArrayList paths = new ArrayList();
IConfiguration config = getDefaultConfiguration(getDefaultTarget());
ITool[] tools = config.getTools();
for (int i = 0; i < tools.length; i++) {
ITool tool = tools[i];
IOption[] opts = tool.getOptions();
for (int j = 0; j < opts.length; j++) {
IOption option = opts[j];
if (option.getValueType() == IOption.INCLUDE_PATH) {
try {
paths.addAll(Arrays.asList(option.getIncludePaths()));
} catch (BuildException e) {
// we should never get here
continue;
}
}
}
}
paths.trimToSize();
return (String[])paths.toArray(new String[paths.size()]);
}
}

View file

@ -14,6 +14,7 @@ package org.eclipse.cdt.core;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IProject;
@ -45,6 +46,22 @@ public class ManagedCProjectNature implements IProjectNature {
// Add the builder to the project
IProjectDescription description = project.getDescription();
ICommand[] commands = description.getBuildSpec();
// TODO Remove this when the new StandardBuild nature adds the cbuilder
for (int i = 0; i < commands.length; i++) {
ICommand command = commands[i];
if (command.getBuilderName().equals("org.eclipse.cdt.core.cbuilder")) {
// Remove the command
Vector vec = new Vector(Arrays.asList(commands));
vec.removeElementAt(i);
vec.trimToSize();
ICommand[] tempCommands = (ICommand[]) vec.toArray(new ICommand[commands.length-1]);
description.setBuildSpec(tempCommands);
break;
}
}
commands = description.getBuildSpec();
boolean found = false;
// See if the builder is already there
for (int i = 0; i < commands.length; ++i) {

View file

@ -7,5 +7,15 @@
CBuilder.build_error= Build Error
# Generated makefile builder messages
MakeBuilder.message.rebuild = Regenerating makefile for project {0}
MakeBuilder.message.incremental = Updating makefile for project {0}
MakeBuilder.message.starting = Starting the build for project {0}
MakeBuilder.message.rebuild = Regenerating makefiles for project {0}
MakeBuilder.message.incremental = Updating makefiles for project {0}
MakeBuilder.message.make = Calling {0} for project {1}
MakeBuilder.message.error = Build error
MakeBuilder.message.finished = Build complete for project {0}
MakeBuilder.comment.module.list = # Every module must be described here
MakeBuilder.comment.source.list = # Each module must contribute its source files here
MakeBuilder.comment.build.rule = # Each module must supply rules for building sources it contributes
MakeBuilder.comment.module.make.includes = # Include the makefiles for each source module
MakeBuilder.comment.module.dep.includes = # Include automatically-generated dependency list:
MakeBuilder.comment.autodeps = # Automatically-generated dependency list:

View file

@ -12,19 +12,34 @@ package org.eclipse.cdt.internal.core;
* **********************************************************************/
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.CommandLauncher;
import org.eclipse.cdt.core.ConsoleOutputStream;
import org.eclipse.cdt.core.ErrorParserManager;
import org.eclipse.cdt.core.build.managed.IManagedBuildInfo;
import org.eclipse.cdt.core.build.managed.ManagedBuildManager;
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.core.resources.MakeUtil;
import org.eclipse.cdt.internal.core.model.Util;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
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.IResourceStatus;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
@ -33,18 +48,27 @@ 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.SubProgressMonitor;
public class GeneratedMakefileBuilder extends ACBuilder {
// String constants
private static final String MESSAGE = "MakeBuilder.message"; //$NON-NLS-1$
private static final String REBUILD = MESSAGE + ".rebuild"; //$NON-NLS-1$
private static final String BUILD_ERROR = MESSAGE + ".error"; //$NON-NLS-1$
private static final String BUILD_FINISHED = MESSAGE + ".finished"; //$NON-NLS-1$
private static final String INCREMENTAL = MESSAGE + ".incremental"; //$NON-NLS-1$
private static final String FILENAME = "makefile"; //$NON-NLS-1$
private static final String NEWLINE = System.getProperty("line.separator", "\n"); //$NON-NLS-1$
private static final String COLON = ":";
private static final String TAB = "\t"; //$NON-NLS-1$
private static final String MAKE = MESSAGE + ".make"; //$NON-NLS-1$
private static final String REBUILD = MESSAGE + ".rebuild"; //$NON-NLS-1$
private static final String START = MESSAGE + ".starting"; //$NON-NLS-1$
public class MyResourceDeltaVisitor implements IResourceDeltaVisitor {
// Status codes
public static final int EMPTY_PROJECT_BUILD_ERROR = 1;
// Local variables
protected List resourcesToBuild;
protected List ruleList;
public class ResourceDeltaVisitor implements IResourceDeltaVisitor {
boolean bContinue;
public boolean visit(IResourceDelta delta) throws CoreException {
@ -67,102 +91,21 @@ public class GeneratedMakefileBuilder extends ACBuilder {
super();
}
/**
* Add whatever macros we can figure out to the makefile.
*
* @param buffer
*/
private void addMacros(StringBuffer buffer, IManagedBuildInfo info) {
// TODO this should come from the build model
buffer.append("RM = rm -f" + NEWLINE);
buffer.append("MAKE = make" + NEWLINE);
buffer.append(NEWLINE);
}
private void addRule(StringBuffer buffer, IPath sourcePath, String outputName, IManagedBuildInfo info) {
// Add the rule to the makefile
buffer.append(outputName + COLON + " " + sourcePath.toString());
// Add all of the dependencies on the source file
buffer.append(NEWLINE);
String ext = sourcePath.getFileExtension();
String cmd = info.getToolForSource(ext);
String flags = info.getFlagsForSource(ext);
buffer.append(TAB + cmd + " " + flags + " " + "$?" + NEWLINE + NEWLINE);
}
/**
* Creates a list of dependencies on project resources.
*
* @param buffer
*/
private void addSources(StringBuffer buffer, IManagedBuildInfo info) throws CoreException {
// Add the list of project files to be built
buffer.append("OBJS = \\" + NEWLINE);
//Get a list of files from the project
IResource[] members = getProject().members();
for (int i = 0; i < members.length; i++) {
IResource resource = members[i];
IPath sourcePath = resource.getProjectRelativePath().removeFileExtension();
String srcExt = resource.getFileExtension();
String outExt = info.getOutputExtension(srcExt);
if (outExt != null) {
// Add the extension back to path
IPath outputPath = sourcePath.addFileExtension(outExt);
// Add the file to the list of dependencies for the base target
buffer.append(outputPath.toString() + " \\" + NEWLINE);
}
}
buffer.append(NEWLINE);
// Add a rule for building each resource to the makefile
for (int j = 0; j < members.length; j++) {
IResource resource = members[j];
IPath sourcePath = resource.getProjectRelativePath().removeFileExtension();
String srcExt = resource.getFileExtension();
String outExt = info.getOutputExtension(srcExt);
if (outExt != null) {
// Add the extension back to path
IPath outputPath = sourcePath.addFileExtension(outExt);
addRule(buffer, resource.getProjectRelativePath(), outputPath.toString(), info);
}
}
}
/**
* @param buffer
*/
private void addTargets(StringBuffer buffer, IManagedBuildInfo info) {
// Generate a rule per source
// This is the top build rule
String flags = info.getFlagsForTarget("exe") + " ";
String cmd = info.getToolForTarget("exe") + " ";
buffer.append(info.getBuildArtifactName() + COLON + " ${OBJS}" + NEWLINE);
buffer.append(TAB + cmd + flags + "$@ ${OBJS}" + NEWLINE);
buffer.append(NEWLINE);
// TODO Generate 'all' for now but determine the real rules from UI
buffer.append("all: " + info.getBuildArtifactName() + NEWLINE);
buffer.append(NEWLINE);
// Always add a clean target
buffer.append("clean:" + NEWLINE);
buffer.append(TAB + "$(RM) *.o " + info.getBuildArtifactName() + NEWLINE);
buffer.append(NEWLINE);
}
/* (non-Javadoc)
* @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 = CCorePlugin.getFormattedString(START, getProject().getName());
if (statusMsg != null) {
monitor.subTask(statusMsg);
}
if (kind == IncrementalProjectBuilder.FULL_BUILD) {
fullBuild(monitor);
}
else {
// Create a delta visitor to make sure we should be rebuilding
MyResourceDeltaVisitor visitor = new MyResourceDeltaVisitor();
ResourceDeltaVisitor visitor = new ResourceDeltaVisitor();
IResourceDelta delta = getDelta(getProject());
if (delta == null) {
fullBuild(monitor);
@ -176,52 +119,107 @@ public class GeneratedMakefileBuilder extends ACBuilder {
}
// Checking to see if the user cancelled the build
checkCancel(monitor);
// Build referenced projects
// Ask build mechanism to compute deltas for project dependencies next time
return getProject().getReferencedProjects();
}
/**
* Check whether the build has been canceled.
* Check whether the build has been canceled. Cancellation requests
* propagated to the caller by throwing <code>OperationCanceledException</code>.
*
* @see org.eclipse.core.runtime.OperationCanceledException#OperationCanceledException()
*/
public void checkCancel(IProgressMonitor monitor) {
if (monitor != null && monitor.isCanceled())
if (monitor != null && monitor.isCanceled()) {
throw new OperationCanceledException();
}
}
/**
* @param monitor
*/
private void fullBuild(IProgressMonitor monitor) throws CoreException {
// Rebuild the entire project
IProject currentProject = getProject();
String statusMsg = null;
// Need to report status to the user
protected void fullBuild(IProgressMonitor monitor) throws CoreException {
// Always need one of these bad boys
if (monitor == null) {
monitor = new NullProgressMonitor();
}
statusMsg = CCorePlugin.getFormattedString(REBUILD, currentProject.getName());
// We also need one of these ...
IProject currentProject = getProject();
if (currentProject == null) {
// Flag some sort of error and bail
return;
}
// Regenerate the makefiles for any managed projects this project depends on
IProject[] deps = currentProject.getReferencedProjects();
for (int i = 0; i < deps.length; i++) {
IProject depProject = deps[i];
if (ManagedBuildManager.manages(depProject)) {
IManagedBuildInfo depInfo = ManagedBuildManager.getBuildInfo(depProject);
MakefileGenerator generator = new MakefileGenerator(depProject, depInfo, monitor);
try {
generator.regenerateMakefiles();
} catch (CoreException e) {
// This may be an empty project exception
if (e.getStatus().getCode() == GeneratedMakefileBuilder.EMPTY_PROJECT_BUILD_ERROR) {
// Just keep looking for other projects
continue;
}
}
}
}
// Need to report status to the user
String statusMsg = CCorePlugin.getFormattedString(REBUILD, currentProject.getName());
monitor.subTask(statusMsg);
// Get a filehandle for the makefile
IPath filePath = getWorkingDirectory().append(IPath.SEPARATOR + FILENAME);
String temp = filePath.toString();
IFile fileHandle = getMakefile(filePath, monitor);
// Regenerate the makefiles for this project
IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(getProject());
MakefileGenerator generator = new MakefileGenerator(currentProject, info, monitor);
try {
generator.regenerateMakefiles();
} catch (CoreException e) {
// See if this is an empty project
if (e.getStatus().getCode() == GeneratedMakefileBuilder.EMPTY_PROJECT_BUILD_ERROR) {
monitor.worked(1);
return;
}
}
IPath topBuildDir = generator.getTopBuildDir();
// Add the items to the makefile
populateMakefile(fileHandle, monitor);
// Now call make
invokeMake(true, topBuildDir.removeFirstSegments(1), info, monitor);
monitor.worked(1);
}
protected IPath getBuildDirectory(String dirName) throws CoreException {
// Create or get the handle for the build directory
IFolder folder = getProject().getFolder(dirName);
if (!folder.exists()) {
try {
folder.create(false, true, null);
}
catch (CoreException e) {
if (e.getStatus().getCode() == IResourceStatus.PATH_OCCUPIED)
folder.refreshLocal(IResource.DEPTH_ZERO, null);
else
throw e;
}
}
return folder.getFullPath();
}
/**
* Gets the makefile for the project. It may be empty.
*
* @return The <code>IFile</code> to generate the makefile into.
*/
public IFile getMakefile(IPath filePath, IProgressMonitor monitor) throws CoreException {
protected IFile getMakefile(IPath filePath, IProgressMonitor monitor) throws CoreException {
// Create or get the handle for the makefile
IWorkspaceRoot root= CCorePlugin.getWorkspace().getRoot();
IWorkspaceRoot root = CCorePlugin.getWorkspace().getRoot();
IFile newFile = root.getFileForLocation(filePath);
if (newFile == null) {
newFile = root.getFile(filePath);
@ -242,6 +240,45 @@ public class GeneratedMakefileBuilder extends ACBuilder {
return newFile;
}
/**
* @param makefilePath
* @param info
* @return
*/
protected String[] getMakeTargets() {
List args = new ArrayList();
// Add each target
String sessionTarget = MakeUtil.getSessionTarget(getProject());
StringTokenizer tokens = new StringTokenizer(sessionTarget);
while (tokens.hasMoreTokens()) {
args.add(tokens.nextToken().trim());
}
if (args.isEmpty()) {
args.add("all");
}
return (String[])args.toArray(new String[args.size()]);
}
/**
* @return
*/
protected List getResourcesToBuild() {
if (resourcesToBuild == null) {
resourcesToBuild = new ArrayList();
}
return resourcesToBuild;
}
/**
* @return
*/
protected List getRuleList() {
if (ruleList == null) {
ruleList = new ArrayList();
}
return ruleList;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.resources.ACBuilder#getWorkingDirectory()
*/
@ -257,7 +294,7 @@ public class GeneratedMakefileBuilder extends ACBuilder {
* @param delta
* @param monitor
*/
private void incrementalBuild(IResourceDelta delta, IProgressMonitor monitor) throws CoreException {
protected void incrementalBuild(IResourceDelta delta, IProgressMonitor monitor) throws CoreException {
// Rebuild the resource tree in the delta
IProject currentProject = getProject();
String statusMsg = null;
@ -269,38 +306,140 @@ public class GeneratedMakefileBuilder extends ACBuilder {
statusMsg = CCorePlugin.getFormattedString(INCREMENTAL, currentProject.getName());
monitor.subTask(statusMsg);
// Get a filehandle for the makefile
IPath filePath = getWorkingDirectory().append(IPath.SEPARATOR + FILENAME);
IFile fileHandle = getMakefile(filePath, monitor);
// Now populate it
populateMakefile(fileHandle, monitor);
IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(getProject());
IPath buildDir = new Path(info.getConfigurationName());
invokeMake(false, buildDir, info, monitor);
monitor.worked(1);
}
/**
* Recreate the entire contents of the makefile.
*
* @param fileHandle The file to place the contents in.
*/
private void populateMakefile(IFile fileHandle, IProgressMonitor monitor) throws CoreException {
// Write out the contents of the build model
StringBuffer buffer = new StringBuffer();
IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(getProject());
protected void invokeMake(boolean fullBuild, IPath buildDir, IManagedBuildInfo info, IProgressMonitor monitor) {
boolean isCanceled = false;
IProject currentProject = getProject();
SubProgressMonitor subMonitor = null;
if (monitor == null) {
monitor = new NullProgressMonitor();
}
// Add the macro definitions
addMacros(buffer, info);
// Flag to the user that make is about to be called
IPath makeCommand = new Path(info.getMakeCommand());
String[] msgs = new String[2];
msgs[0] = info.getMakeCommand();
msgs[1] = currentProject.getName();
String statusMsg = CCorePlugin.getFormattedString(MAKE, msgs);
if (statusMsg != null) {
monitor.subTask(statusMsg);
}
// Add a list of source files
addSources(buffer, info);
// Get a build console for the project
IConsole console = null;
ConsoleOutputStream consoleOutStream = null;
IWorkspace workspace = null;
IMarker[] markers = null;
try {
console = CCorePlugin.getDefault().getConsole();
console.start(currentProject);
consoleOutStream = console.getOutputStream();
// Add targets
addTargets(buffer, info);
// Remove all markers for this project
workspace = currentProject.getWorkspace();
markers = currentProject.findMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE);
if (markers != null) {
workspace.deleteMarkers(markers);
}
} catch (CoreException e) {
}
// Save the file
Util.save(buffer, fileHandle);
IPath workingDirectory = getWorkingDirectory().append(buildDir);
// Get the arguments to be passed to make from build model
String[] makeTargets = getMakeTargets();
// Get a launcher for the make command
String errMsg = null;
CommandLauncher launcher = new CommandLauncher();
launcher.showCommand(true);
// Set the environmennt, some scripts may need the CWD var to be set.
Properties props = launcher.getEnvironment();
props.put("CWD", workingDirectory.toOSString());
props.put("PWD", workingDirectory.toOSString());
String[] env = null;
ArrayList envList = new ArrayList();
Enumeration names = props.propertyNames();
if (names != null) {
while (names.hasMoreElements()) {
String key = (String) names.nextElement();
envList.add(key + "=" + props.getProperty(key));
}
env = (String[]) envList.toArray(new String[envList.size()]);
}
// Hook up an error parser
ErrorParserManager epm = new ErrorParserManager(this);
epm.setOutputStream(consoleOutStream);
OutputStream stdout = epm.getOutputStream();
OutputStream stderr = epm.getOutputStream();
// Launch make
Process proc = launcher.execute(makeCommand, makeTargets, env, workingDirectory);
if (proc != null) {
try {
// Close the input of the Process explicitely.
// We will never write to it.
proc.getOutputStream().close();
} catch (IOException e) {
}
subMonitor = new SubProgressMonitor(monitor, IProgressMonitor.UNKNOWN);
if (launcher.waitAndRead(stdout, stderr, subMonitor) != CommandLauncher.OK) {
errMsg = launcher.getErrorMessage();
isCanceled = monitor.isCanceled();
monitor.setCanceled(false);
subMonitor = new SubProgressMonitor(monitor, IProgressMonitor.UNKNOWN);
subMonitor.subTask("Refresh From Local");
try {
currentProject.refreshLocal(IResource.DEPTH_INFINITE, subMonitor);
} catch (CoreException e) {
}
subMonitor = new SubProgressMonitor(monitor, IProgressMonitor.UNKNOWN);
subMonitor.subTask("Parsing");
} else {
errMsg = launcher.getErrorMessage();
}
// Report either the success or failure of our mission
StringBuffer buf = new StringBuffer();
if (errMsg != null && errMsg.length() > 0) {
String errorDesc = CCorePlugin.getResourceString(BUILD_ERROR);
buf.append(errorDesc);
buf.append(System.getProperty("line.separator", "\n"));
buf.append("(").append(errMsg).append(")");
}
else {
// Report a successful build
String successMsg = CCorePlugin.getFormattedString(BUILD_FINISHED, currentProject.getName());
buf.append(successMsg);
buf.append(System.getProperty("line.separator", "\n"));
}
// Write your message on the pavement
try {
consoleOutStream.write(buf.toString().getBytes());
consoleOutStream.flush();
stdout.close();
stderr.close();
} catch (IOException e) {
}
epm.reportProblems();
subMonitor.done();
monitor.setCanceled(isCanceled);
}
monitor.done();
}
}

View file

@ -0,0 +1,574 @@
package org.eclipse.cdt.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.build.managed.IManagedBuildInfo;
import org.eclipse.cdt.core.search.ICSearchConstants;
import org.eclipse.cdt.internal.core.model.Util;
import org.eclipse.cdt.internal.core.sourcedependency.DependencyManager;
import org.eclipse.cdt.internal.core.sourcedependency.DependencyQueryJob;
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.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.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
public class MakefileGenerator {
// String constants for messages
private static final String MESSAGE = "MakeBuilder.message"; //$NON-NLS-1$
private static final String BUILD_ERROR = MESSAGE + ".error"; //$NON-NLS-1$
private static final String COMMENT = "MakeBuilder.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 = "module.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 = "module.mk"; //$NON-NLS-1$
protected static final String LINEBREAK = "\\";
protected static final String NEWLINE = System.getProperty("line.separator");
protected static final String SEMI_COLON = ";";
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 moduleList;
protected IProgressMonitor monitor;
protected IProject project;
protected List ruleList;
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 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)) {
generator.appendModule(resource);
}
return false;
}
// Recurse into subdirectories
return true;
}
}
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;
}
/**
* @param module
* @return
*/
protected StringBuffer addDeps(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(CCorePlugin.getResourceString(AUTO_DEP) + NEWLINE);
DependencyManager dependencyManager = CCorePlugin.getDefault().getCoreModel().getDependencyManager();
/*
* 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 {
dependencyManager.performConcurrentJob(new DependencyQueryJob(project, (IFile)resource, dependencyManager, dependencies), ICSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, 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;
}
/**
* @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);
// Add the macro for the output flag
buffer.append("OUTPUT_FLAG := ");
buffer.append(info.getOutputFlag() + NEWLINE);
buffer.append(CCorePlugin.getResourceString(SRC_LISTS) + NEWLINE);
buffer.append("C_SRCS := " + NEWLINE);
buffer.append("CC_SRCS := " + NEWLINE);
buffer.append(NEWLINE + NEWLINE);
return buffer;
}
/**
* @return
*/
protected StringBuffer addModules() {
StringBuffer buffer = new StringBuffer();
// Add the comment
buffer.append(CCorePlugin.getResourceString(MOD_LIST) + NEWLINE);
buffer.append("MODULES := " + LINEBREAK + NEWLINE);
buffer.append("." + LINEBREAK + NEWLINE);
// Get all the module names
ListIterator iter = getModuleList().listIterator();
while (iter.hasNext()) {
IContainer container = (IContainer) iter.next();
IPath path = container.getProjectRelativePath();
buffer.append(path.toString() + WHITESPACE + LINEBREAK + NEWLINE);
}
buffer.append(NEWLINE);
buffer.append(CCorePlugin.getResourceString(MOD_INCL) + NEWLINE);
buffer.append("include ${patsubst %, %/module.mk, $(MODULES)}" + NEWLINE);
buffer.append(NEWLINE + NEWLINE);
return buffer;
}
/**
* Answers a <code>StringBuffer</code> containing all of the sources contributed by
* a container to the build.
* @param module
* @return
*/
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 ruleBuffer = new StringBuffer(CCorePlugin.getResourceString(MOD_RULES) + NEWLINE);
// Put the comment in
buffer.append(CCorePlugin.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)) {
// TODO use build model to determine what list the file goes in
ccBuffer.append(resource.getName() + WHITESPACE + LINEBREAK + NEWLINE);
// Try to add the rule for the file
addRule(relativePath, ruleBuffer, resource);
}
}
}
// Finish the commands in the buffers
cBuffer.append("}" + NEWLINE + NEWLINE);
ccBuffer.append("}" + NEWLINE + NEWLINE);
// Append them all together
buffer.append(cBuffer).append(ccBuffer).append(ruleBuffer);
return buffer;
}
/**
* Answers a <code>StrinBuffer</code> containing all of the required targets to
* properly build the project.
*/
protected StringBuffer addTargets() {
StringBuffer buffer = new StringBuffer();
// Get the target and it's extension
String target = info.getBuildArtifactName();
IPath temp = new Path(target);
String extension = temp.getFileExtension();
/*
* Write out the taqrget rule as:
* <target>.<extension>: $(CC_SRCS:$(ROOT)/%.cpp=%.o) $(C_SRCS:$(ROOT)/%.c=%.o)
* $(BUILD_TOOL) $(FLAGS) $(OUTPUT_FLAG) $@ $^ $(LIB_DEPS)
*/
String cmd = info.getToolForTarget(extension);
String flags = info.getFlagsForTarget(extension);
buffer.append(target + COLON + WHITESPACE + "$(CC_SRCS:$(ROOT)/%.cpp=%.o) $(C_SRCS:$(ROOT)/%.c=%.o)" + NEWLINE);
buffer.append(TAB + cmd + WHITESPACE + flags + WHITESPACE + "$(OUTPUT_FLAG) $@" + WHITESPACE + "$^" + WHITESPACE + NEWLINE);
buffer.append(NEWLINE);
// TODO Generate 'all' for now but determine the real rules from UI
buffer.append("all: " + target + NEWLINE);
buffer.append(NEWLINE);
// Always add a clean target
buffer.append(".PHONY: clean" + NEWLINE);
buffer.append("clean:" + NEWLINE);
buffer.append(TAB + "$(RM)" + WHITESPACE + "${addprefix ., $(CC_SRCS:$(ROOT)%.cpp=%.o)} ${addprefix ., $(C_SRCS:$(ROOT)%.c=%.o)}" + WHITESPACE + target + NEWLINE);
buffer.append(NEWLINE);
buffer.append(NEWLINE + CCorePlugin.getResourceString(DEP_INCL) + NEWLINE);
buffer.append("include ${patsubst %, %/module.dep, $(MODULES)}" + NEWLINE);
buffer.append(NEWLINE);
return buffer;
}
protected void addRule(String relativePath, StringBuffer buffer, IResource resource) {
String rule = null;
String cmd = null;
String buildFlags = null;
String inputExtension = null;
String outputExtension = 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);
buffer.append(TAB + cmd + WHITESPACE + buildFlags + WHITESPACE + "$(OUTPUT_FLAG) $@" + WHITESPACE + "$<" + NEWLINE + NEWLINE);
}
}
/**
* @param resource
*/
public void appendModule(IResource resource) {
// The build model knows how to build this file
IContainer container = resource.getParent();
if (!getModuleList().contains(container)) {
getModuleList().add(container);
}
}
/**
* Check whether the build has been canceled. 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();
}
}
/**
* @return
*/
private List getModuleList() {
if (moduleList == null) {
moduleList = new ArrayList();
}
return moduleList;
}
/**
*
*/
private List getRuleList() {
if (ruleList == null) {
ruleList = new ArrayList();
}
return ruleList;
}
/**
* @param string
* @return
*/
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();
}
/**
* @param makefilePath
* @param monitor
* @return
*/
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;
}
// TODO handle long running file operation
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
*/
public IPath getTopBuildDir() {
return topBuildDir;
}
/**
* Create the entire contents of the makefile.
*
* @param fileHandle The file to place the contents in.
* @param info
* @param monitor
*/
protected void populateMakefile(IFile fileHandle) {
StringBuffer buffer = new StringBuffer();
// Add the macro definitions
buffer.append(addMacros());
// Append the module list
buffer.append(addModules());
// Add targets
buffer.append(addTargets());
// Save the file
try {
Util.save(buffer, fileHandle);
} catch (CoreException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
/**
* @param module
*/
protected void populateModMakefile(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(addDeps(module));
// Save the files
Util.save(makeBuf, modMakefile);
Util.save(depBuf, modDepfile);
}
public void regenerateMakefiles() throws CoreException {
// Visit the resources in the project
ResourceProxyVisitor visitor = new ResourceProxyVisitor(this, info);
project.accept(visitor, IResource.NONE);
if (getModuleList().isEmpty()) {
// There is nothing to build
IStatus status = new Status(IStatus.INFO, CCorePlugin.PLUGIN_ID, GeneratedMakefileBuilder.EMPTY_PROJECT_BUILD_ERROR, "", null);
throw new CoreException(status);
}
// See if the user has cancelled the build
checkCancel();
// 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);
// Populate the makefile
populateMakefile(makefileHandle);
checkCancel();
// Now populate the module makefiles
ListIterator iter = getModuleList().listIterator();
while (iter.hasNext()) {
populateModMakefile((IContainer)iter.next());
checkCancel();
}
}
}