diff options
author | mattinger <[email protected]> | 2006-11-07 21:16:39 +0000 |
---|---|---|
committer | mattinger <[email protected]> | 2006-11-07 21:16:39 +0000 |
commit | c8da7ec534c959db815f272819dafaf61e49a9bd (patch) | |
tree | 16dfe231dadf33c0829ca23efe8a0021502d99eb /src/net/sf/antcontrib/cpptasks/compiler | |
parent | 93d3419f7217a29d266acf2884c6327f1953cb3f (diff) |
Initial import of cpptasks code
git-svn-id: file:///home/sven/projects/JOGL/temp/ant-contrib/svn/ant-contrib-code/trunk/cpptasks@62 32d7a393-a5a9-423c-abd3-5d954feb1f2f
Diffstat (limited to 'src/net/sf/antcontrib/cpptasks/compiler')
21 files changed, 2570 insertions, 0 deletions
diff --git a/src/net/sf/antcontrib/cpptasks/compiler/AbstractCompiler.java b/src/net/sf/antcontrib/cpptasks/compiler/AbstractCompiler.java new file mode 100644 index 0000000..e61bd64 --- /dev/null +++ b/src/net/sf/antcontrib/cpptasks/compiler/AbstractCompiler.java @@ -0,0 +1,208 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; +import java.util.Vector; +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.CompilerDef; +import net.sf.antcontrib.cpptasks.DependencyInfo; +import net.sf.antcontrib.cpptasks.ProcessorDef; +import net.sf.antcontrib.cpptasks.parser.Parser; +import net.sf.antcontrib.cpptasks.TargetDef; +import net.sf.antcontrib.cpptasks.VersionInfo; + +/** + * An abstract compiler implementation. + * + * @author Adam Murdoch + * @author Curt Arnold + */ +public abstract class AbstractCompiler extends AbstractProcessor + implements + Compiler { + private static final String[] emptyIncludeArray = new String[0]; + private String outputSuffix; + protected AbstractCompiler(String[] sourceExtensions, + String[] headerExtensions, String outputSuffix) { + super(sourceExtensions, headerExtensions); + this.outputSuffix = outputSuffix; + } + /** + * Checks file name to see if parse should be attempted + * + * Default implementation returns false for files with extensions '.dll', + * 'tlb', '.res' + * + */ + protected boolean canParse(File sourceFile) { + String sourceName = sourceFile.toString(); + int lastPeriod = sourceName.lastIndexOf('.'); + if (lastPeriod >= 0 && lastPeriod == sourceName.length() - 4) { + String ext = sourceName.substring(lastPeriod).toUpperCase(); + if (ext.equals(".DLL") || ext.equals(".TLB") || ext.equals(".RES")) { + return false; + } + } + return true; + } + abstract protected CompilerConfiguration createConfiguration(CCTask task, + LinkType linkType, ProcessorDef[] baseConfigs, + CompilerDef specificConfig, TargetDef targetPlatform, + VersionInfo versionInfo); + public ProcessorConfiguration createConfiguration(CCTask task, + LinkType linkType, ProcessorDef[] baseConfigs, + ProcessorDef specificConfig, TargetDef targetPlatform, + VersionInfo versionInfo) { + if (specificConfig == null) { + throw new NullPointerException("specificConfig"); + } + return createConfiguration(task, linkType, baseConfigs, + (CompilerDef) specificConfig, targetPlatform, versionInfo); + } + abstract protected Parser createParser(File sourceFile); + protected String getBaseOutputName(String inputFile) { + int lastSlash = inputFile.lastIndexOf('/'); + int lastReverse = inputFile.lastIndexOf('\\'); + int lastSep = inputFile.lastIndexOf(File.separatorChar); + if (lastReverse > lastSlash) { + lastSlash = lastReverse; + } + if (lastSep > lastSlash) { + lastSlash = lastSep; + } + int lastPeriod = inputFile.lastIndexOf('.'); + if (lastPeriod < 0) { + lastPeriod = inputFile.length(); + } + return inputFile.substring(lastSlash + 1, lastPeriod); + } + public String[] getOutputFileNames(String inputFile, VersionInfo versionInfo) { + // + // if a recognized input file + // + if (bid(inputFile) > 1) { + String baseName = getBaseOutputName(inputFile); + return new String[] { baseName + outputSuffix }; + } + return new String[0]; + } + /** + * Returns dependency info for the specified source file + * + * @param task + * task for any diagnostic output + * @param source + * file to be parsed + * @param includePath + * include path to be used to resolve included files + * + * @param sysIncludePath + * sysinclude path from build file, files resolved using + * sysInclude path will not participate in dependency analysis + * + * @param envIncludePath + * include path from environment variable, files resolved with + * envIncludePath will not participate in dependency analysis + * + * @param baseDir + * used to produce relative paths in DependencyInfo + * @param includePathIdentifier + * used to distinguish DependencyInfo's from different include + * path settings + * + * @author Curt Arnold + */ + public final DependencyInfo parseIncludes(CCTask task, File source, + File[] includePath, File[] sysIncludePath, File[] envIncludePath, + File baseDir, String includePathIdentifier) { + // + // if any of the include files can not be identified + // change the sourceLastModified to Long.MAX_VALUE to + // force recompilation of anything that depends on it + long sourceLastModified = source.lastModified(); + File[] sourcePath = new File[1]; + sourcePath[0] = new File(source.getParent()); + Vector onIncludePath = new Vector(); + Vector onSysIncludePath = new Vector(); + String baseDirPath; + try { + baseDirPath = baseDir.getCanonicalPath(); + } catch (IOException ex) { + baseDirPath = baseDir.toString(); + } + String relativeSource = CUtil.getRelativePath(baseDirPath, source); + String[] includes = emptyIncludeArray; + if (canParse(source)) { + Parser parser = createParser(source); + try { + Reader reader = new BufferedReader(new FileReader(source)); + parser.parse(reader); + includes = parser.getIncludes(); + } catch (IOException ex) { + task.log("Error parsing " + source.toString() + ":" + + ex.toString()); + includes = new String[0]; + } + } + for (int i = 0; i < includes.length; i++) { + String includeName = includes[i]; + if (!resolveInclude(includeName, sourcePath, onIncludePath)) { + if (!resolveInclude(includeName, includePath, onIncludePath)) { + if (!resolveInclude(includeName, sysIncludePath, + onSysIncludePath)) { + if (!resolveInclude(includeName, envIncludePath, + onSysIncludePath)) { + // + // this should be enough to require us to reparse + // the file with the missing include for dependency + // information without forcing a rebuild + sourceLastModified += 2 * CUtil.FILETIME_EPSILON; + } + } + } + } + } + for (int i = 0; i < onIncludePath.size(); i++) { + String relativeInclude = CUtil.getRelativePath(baseDirPath, + (File) onIncludePath.elementAt(i)); + onIncludePath.setElementAt(relativeInclude, i); + } + for (int i = 0; i < onSysIncludePath.size(); i++) { + String relativeInclude = CUtil.getRelativePath(baseDirPath, + (File) onSysIncludePath.elementAt(i)); + onSysIncludePath.setElementAt(relativeInclude, i); + } + return new DependencyInfo(includePathIdentifier, relativeSource, + sourceLastModified, onIncludePath, onSysIncludePath); + } + protected boolean resolveInclude(String includeName, File[] includePath, + Vector onThisPath) { + for (int i = 0; i < includePath.length; i++) { + File includeFile = new File(includePath[i], includeName); + if (includeFile.exists()) { + onThisPath.addElement(includeFile); + return true; + } + } + return false; + } +} diff --git a/src/net/sf/antcontrib/cpptasks/compiler/AbstractLinker.java b/src/net/sf/antcontrib/cpptasks/compiler/AbstractLinker.java new file mode 100644 index 0000000..9de9491 --- /dev/null +++ b/src/net/sf/antcontrib/cpptasks/compiler/AbstractLinker.java @@ -0,0 +1,122 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import java.io.File; +import java.io.IOException; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.LinkerDef; +import net.sf.antcontrib.cpptasks.ProcessorDef; +import net.sf.antcontrib.cpptasks.TargetDef; +import net.sf.antcontrib.cpptasks.TargetMatcher; +import net.sf.antcontrib.cpptasks.VersionInfo; + +import org.apache.tools.ant.types.Environment; +/** + * An abstract Linker implementation. + * + * @author Adam Murdoch + */ +public abstract class AbstractLinker extends AbstractProcessor + implements + Linker { + public AbstractLinker(String[] objExtensions, String[] ignoredExtensions) { + super(objExtensions, ignoredExtensions); + } + /** + * Returns the bid of the processor for the file. + * + * A linker will bid 1 on any unrecognized file type. + * + * @param inputFile + * filename of input file + * @return bid for the file, 0 indicates no interest, 1 indicates that the + * processor recognizes the file but doesn't process it (header + * files, for example), 100 indicates strong interest + */ + public int bid(String inputFile) { + int bid = super.bid(inputFile); + switch (bid) { + // + // unrecognized extension, take the file + // + case 0 : + return 1; + // + // discard the ignored extensions + // + case 1 : + return 0; + } + return bid; + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + return this; + } + abstract protected LinkerConfiguration createConfiguration(CCTask task, + LinkType linkType, ProcessorDef[] baseConfigs, + LinkerDef specificConfig, TargetDef targetPlatform, + VersionInfo versionInfo); + public ProcessorConfiguration createConfiguration(CCTask task, + LinkType linkType, ProcessorDef[] baseConfigs, + ProcessorDef specificConfig, + TargetDef targetPlatform, + VersionInfo versionInfo) { + if (specificConfig == null) { + throw new NullPointerException("specificConfig"); + } + return createConfiguration(task, linkType, baseConfigs, + (LinkerDef) specificConfig, targetPlatform, versionInfo); + } + public String getLibraryKey(File libfile) { + return libfile.getName(); + } + public abstract String[] getOutputFileNames(String fileName, VersionInfo versionInfo); + + + /** + * Adds source or object files to the bidded fileset to + * support version information. + * + * @param versionInfo version information + * @param linkType link type + * @param isDebug true if debug build + * @param executableName name of generated executable + * @param objDir directory for generated files + * @param matcher bidded fileset + */ + public void addVersionFiles(final VersionInfo versionInfo, + final LinkType linkType, + final File outputFile, + final boolean isDebug, + final File objDir, + final TargetMatcher matcher) throws IOException { + if (versionInfo == null) { + throw new NullPointerException("versionInfo"); + } + if (linkType == null) { + throw new NullPointerException("linkType"); + } + if (outputFile == null) { + throw new NullPointerException("outputFile"); + } + if (objDir == null) { + throw new NullPointerException("objDir"); + } + } + +} diff --git a/src/net/sf/antcontrib/cpptasks/compiler/AbstractProcessor.java b/src/net/sf/antcontrib/cpptasks/compiler/AbstractProcessor.java new file mode 100644 index 0000000..d0cd77b --- /dev/null +++ b/src/net/sf/antcontrib/cpptasks/compiler/AbstractProcessor.java @@ -0,0 +1,129 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import org.apache.tools.ant.types.Environment; +/** + * An abstract processor (compiler/linker) implementation. + * + * @author Curt Arnold + */ +public abstract class AbstractProcessor implements Processor, Cloneable { + /** + * default bid for a file name that the processor recognizes but does not + * process and does not want to fall through to the linker + */ + public final static int DEFAULT_DISCARD_BID = 1; + /** + * default bid for a file name that the processor desires to process + */ + public final static int DEFAULT_PROCESS_BID = 100; + /** + * Determines the identification of a command line processor by capture the + * first line of its output for a specific command. + * + * @param command + * array of command line arguments starting with executable + * name. For example, { "cl" } + * @param fallback + * start of identifier if there is an error in executing the + * command + * @return identifier for the processor + */ + protected static String getIdentifier(String[] command, String fallback) { + String identifier = fallback; + try { + String[] cmdout = CaptureStreamHandler.run(command); + if (cmdout.length > 0) { + identifier = cmdout[0]; + } + } catch (Throwable ex) { + identifier = fallback + ":" + ex.toString(); + } + return identifier; + } + private final String[] headerExtensions; + private final String[] sourceExtensions; + protected AbstractProcessor(String[] sourceExtensions, + String[] headerExtensions) { + this.sourceExtensions = (String[]) sourceExtensions.clone(); + this.headerExtensions = (String[]) headerExtensions.clone(); + } + /** + * Returns the bid of the processor for the file. + * + * @param inputFile + * filename of input file + * @return bid for the file, 0 indicates no interest, 1 indicates that the + * processor recognizes the file but doesn't process it (header + * files, for example), 100 indicates strong interest + */ + public int bid(String inputFile) { + String lower = inputFile.toLowerCase(); + for (int i = 0; i < sourceExtensions.length; i++) { + if (lower.endsWith(sourceExtensions[i])) { + return DEFAULT_PROCESS_BID; + } + } + for (int i = 0; i < headerExtensions.length; i++) { + if (lower.endsWith(headerExtensions[i])) { + return DEFAULT_DISCARD_BID; + } + } + return 0; + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + return this; + } + protected Object clone() throws CloneNotSupportedException { + return super.clone(); + } + public String[] getHeaderExtensions() { + return (String[]) this.headerExtensions.clone(); + } + abstract public String getIdentifier(); + /** + * Gets the target operating system architecture + * + * @return String target operating system architecture + */ + protected String getOSArch() { + return System.getProperty("os.arch"); + } + /** + * Gets the target operating system name + * + * @return String target operating system name + */ + protected String getOSName() { + return System.getProperty("os.name"); + } + public String[] getSourceExtensions() { + return (String[]) this.sourceExtensions.clone(); + } + /** + * Returns true if the target operating system is Mac OS X or Darwin. + * + * @return boolean + */ + protected boolean isDarwin() { + String osName = getOSName(); + return "Mac OS X".equals(osName); + } + public final String toString() { + return getIdentifier(); + } +} diff --git a/src/net/sf/antcontrib/cpptasks/compiler/CaptureStreamHandler.java b/src/net/sf/antcontrib/cpptasks/compiler/CaptureStreamHandler.java new file mode 100644 index 0000000..83c59f7 --- /dev/null +++ b/src/net/sf/antcontrib/cpptasks/compiler/CaptureStreamHandler.java @@ -0,0 +1,122 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.util.Vector; + +import org.apache.tools.ant.taskdefs.Execute; +import org.apache.tools.ant.taskdefs.ExecuteStreamHandler; +/** + * Implements ExecuteStreamHandler to capture the output of a Execute to an + * array of strings + * + * @author Curt Arnold + */ +public class CaptureStreamHandler implements ExecuteStreamHandler { + /** + * Runs an executable and captures the output in a String array + * + * @param cmdline + * command line arguments + * @return output of process + */ + public static String[] run(String[] cmdline) { + CaptureStreamHandler handler = new CaptureStreamHandler(); + Execute exec = new Execute(handler); + exec.setCommandline(cmdline); + try { + int status = exec.execute(); + } catch (IOException ex) { + } + return handler.getOutput(); + } + private InputStream errorStream; + private InputStream fromProcess; + public CaptureStreamHandler() { + } + public String[] getOutput() { + String[] output; + if (fromProcess != null) { + Vector lines = new Vector(10); + try { + BufferedReader reader = new BufferedReader( + new InputStreamReader(errorStream)); + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 100; j++) { + String line = reader.readLine(); + if (line == null) { + reader = new BufferedReader(new InputStreamReader( + fromProcess)); + break; + } + lines.addElement(line); + } + } + } catch (IOException ex) { + } + output = new String[lines.size()]; + lines.copyInto(output); + return output; + } + output = new String[0]; + return output; + } + /** + * Install a handler for the error stream of the subprocess. + * + * @param is + * input stream to read from the error stream from the + * subprocess + */ + public void setProcessErrorStream(InputStream is) throws IOException { + errorStream = is; + } + /** + * Install a handler for the input stream of the subprocess. + * + * @param os + * output stream to write to the standard input stream of the + * subprocess + */ + public void setProcessInputStream(OutputStream os) throws IOException { + os.close(); + } + /** + * Install a handler for the output stream of the subprocess. + * + * @param is + * input stream to read from the error stream from the + * subprocess + */ + public void setProcessOutputStream(InputStream is) throws IOException { + fromProcess = is; + } + /** + * Start handling of the streams. + */ + public void start() throws IOException { + } + /** + * Stop handling of the streams - will not be restarted. + */ + public void stop() { + } +} diff --git a/src/net/sf/antcontrib/cpptasks/compiler/CommandLineCCompiler.java b/src/net/sf/antcontrib/cpptasks/compiler/CommandLineCCompiler.java new file mode 100644 index 0000000..adafa08 --- /dev/null +++ b/src/net/sf/antcontrib/cpptasks/compiler/CommandLineCCompiler.java @@ -0,0 +1,42 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import java.io.File; + +import net.sf.antcontrib.cpptasks.parser.CParser; +import net.sf.antcontrib.cpptasks.parser.Parser; + +import org.apache.tools.ant.types.Environment; +/** + * An abstract Compiler implementation which uses an external program to + * perform the compile. + * + * @author Adam Murdoch + */ +public abstract class CommandLineCCompiler extends CommandLineCompiler { + protected CommandLineCCompiler(String command, String identifierArg, + String[] sourceExtensions, String[] headerExtensions, + String outputSuffix, boolean libtool, + CommandLineCCompiler libtoolCompiler, boolean newEnvironment, + Environment env) { + super(command, identifierArg, sourceExtensions, headerExtensions, + outputSuffix, libtool, libtoolCompiler, newEnvironment, env); + } + protected Parser createParser(File source) { + return new CParser(); + } +} diff --git a/src/net/sf/antcontrib/cpptasks/compiler/CommandLineCompiler.java b/src/net/sf/antcontrib/cpptasks/compiler/CommandLineCompiler.java new file mode 100644 index 0000000..a8b7691 --- /dev/null +++ b/src/net/sf/antcontrib/cpptasks/compiler/CommandLineCompiler.java @@ -0,0 +1,437 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import java.io.File; +import java.io.IOException; +import java.util.Enumeration; +import java.util.Vector; +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.CompilerDef; +import net.sf.antcontrib.cpptasks.ProcessorDef; +import net.sf.antcontrib.cpptasks.ProcessorParam; +import net.sf.antcontrib.cpptasks.types.CommandLineArgument; +import net.sf.antcontrib.cpptasks.types.UndefineArgument; +import net.sf.antcontrib.cpptasks.TargetDef; +import net.sf.antcontrib.cpptasks.VersionInfo; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.types.Environment; +import net.sf.antcontrib.cpptasks.OptimizationEnum;; +/** + * An abstract Compiler implementation which uses an external program to + * perform the compile. + * + * @author Adam Murdoch + */ +public abstract class CommandLineCompiler extends AbstractCompiler { + private String command; + private final Environment env; + private String identifier; + private String identifierArg; + private boolean libtool; + private CommandLineCompiler libtoolCompiler; + private final boolean newEnvironment; + protected CommandLineCompiler(String command, String identifierArg, + String[] sourceExtensions, String[] headerExtensions, + String outputSuffix, boolean libtool, + CommandLineCompiler libtoolCompiler, boolean newEnvironment, + Environment env) { + super(sourceExtensions, headerExtensions, outputSuffix); + this.command = command; + if (libtool && libtoolCompiler != null) { + throw new java.lang.IllegalArgumentException( + "libtoolCompiler should be null when libtool is true"); + } + this.libtool = libtool; + this.libtoolCompiler = libtoolCompiler; + this.identifierArg = identifierArg; + this.newEnvironment = newEnvironment; + this.env = env; + } + abstract protected void addImpliedArgs(Vector args, boolean debug, + boolean multithreaded, boolean exceptions, LinkType linkType, + Boolean rtti, OptimizationEnum optimization); + /** + * Adds command-line arguments for include directories. + * + * If relativeArgs is not null will add corresponding relative paths + * include switches to that vector (for use in building a configuration + * identifier that is consistent between machines). + * + * @param baseDirPaths + * A vector containing the parts of the working directory, + * produced by CUtil.DecomposeFile. + * @param includeDirs + * Array of include directory paths + * @param args + * Vector of command line arguments used to execute the task + * @param relativeArgs + * Vector of command line arguments used to build the + * configuration identifier + */ + protected void addIncludes(String baseDirPath, File[] includeDirs, + Vector args, Vector relativeArgs, StringBuffer includePathId) { + for (int i = 0; i < includeDirs.length; i++) { + args.addElement(getIncludeDirSwitch(includeDirs[i] + .getAbsolutePath())); + if (relativeArgs != null) { + String relative = CUtil.getRelativePath(baseDirPath, + includeDirs[i]); + relativeArgs.addElement(getIncludeDirSwitch(relative)); + if (includePathId != null) { + if (includePathId.length() == 0) { + includePathId.append("/I"); + } else { + includePathId.append(" /I"); + } + includePathId.append(relative); + } + } + } + } + abstract protected void addWarningSwitch(Vector args, int warnings); + protected void buildDefineArguments(CompilerDef[] defs, Vector args) { + // + // assume that we aren't inheriting defines from containing <cc> + // + UndefineArgument[] merged = defs[0].getActiveDefines(); + for (int i = 1; i < defs.length; i++) { + // + // if we are inheriting, merge the specific defines with the + // containing defines + merged = UndefineArgument.merge(defs[i].getActiveDefines(), merged); + } + StringBuffer buf = new StringBuffer(30); + for (int i = 0; i < merged.length; i++) { + buf.setLength(0); + UndefineArgument current = merged[i]; + if (current.isDefine()) { + getDefineSwitch(buf, current.getName(), current.getValue()); + } else { + getUndefineSwitch(buf, current.getName()); + } + args.addElement(buf.toString()); + } + } + /** + * Compiles a source file. + * + * @author Curt Arnold + */ + public void compile(CCTask task, File outputDir, String[] sourceFiles, + String[] args, String[] endArgs, boolean relentless, + CommandLineCompilerConfiguration config, ProgressMonitor monitor) + throws BuildException { + BuildException exc = null; + // + // determine length of executable name and args + // + String command = getCommand(); + int baseLength = command.length() + args.length + endArgs.length; + if (libtool) { + baseLength += 8; + } + for (int i = 0; i < args.length; i++) { + baseLength += args[i].length(); + } + for (int i = 0; i < endArgs.length; i++) { + baseLength += endArgs[i].length(); + } + if (baseLength > getMaximumCommandLength()) { + throw new BuildException( + "Command line is over maximum length without specifying source file"); + } + // + // typically either 1 or Integer.MAX_VALUE + // + int maxInputFilesPerCommand = getMaximumInputFilesPerCommand(); + int argumentCountPerInputFile = getArgumentCountPerInputFile(); + for (int sourceIndex = 0; sourceIndex < sourceFiles.length;) { + int cmdLength = baseLength; + int firstFileNextExec; + for (firstFileNextExec = sourceIndex; firstFileNextExec < sourceFiles.length + && (firstFileNextExec - sourceIndex) < maxInputFilesPerCommand; firstFileNextExec++) { + cmdLength += getTotalArgumentLengthForInputFile(outputDir, + sourceFiles[firstFileNextExec]); + if (cmdLength >= getMaximumCommandLength()) + break; + } + if (firstFileNextExec == sourceIndex) { + throw new BuildException( + "Extremely long file name, can't fit on command line"); + } + int argCount = args.length + 1 + endArgs.length + + (firstFileNextExec - sourceIndex) + * argumentCountPerInputFile; + if (libtool) { + argCount++; + } + String[] commandline = new String[argCount]; + int index = 0; + if (libtool) { + commandline[index++] = "libtool"; + } + commandline[index++] = command; + for (int j = 0; j < args.length; j++) { + commandline[index++] = args[j]; + } + for (int j = sourceIndex; j < firstFileNextExec; j++) { + for (int k = 0; k < argumentCountPerInputFile; k++) { + commandline[index++] = getInputFileArgument(outputDir, + sourceFiles[j], k); + } + } + for (int j = 0; j < endArgs.length; j++) { + commandline[index++] = endArgs[j]; + } + int retval = runCommand(task, outputDir, commandline); + if (monitor != null) { + String[] fileNames = new String[firstFileNextExec - sourceIndex]; + for (int j = 0; j < fileNames.length; j++) { + fileNames[j] = sourceFiles[sourceIndex + j]; + } + monitor.progress(fileNames); + } + // + // if the process returned a failure code and + // we aren't holding an exception from an earlier + // interation + if (retval != 0 && exc == null) { + // + // construct the exception + // + exc = new BuildException(this.getCommand() + + " failed with return code " + retval, task + .getLocation()); + // + // and throw it now unless we are relentless + // + if (!relentless) { + throw exc; + } + } + sourceIndex = firstFileNextExec; + } + // + // if the compiler returned a failure value earlier + // then throw an exception + if (exc != null) { + throw exc; + } + } + protected CompilerConfiguration createConfiguration(final CCTask task, + final LinkType linkType, + final ProcessorDef[] baseDefs, + final CompilerDef specificDef, + final TargetDef targetPlatform, + final VersionInfo versionInfo) { + Vector args = new Vector(); + CompilerDef[] defaultProviders = new CompilerDef[baseDefs.length + 1]; + for (int i = 0; i < baseDefs.length; i++) { + defaultProviders[i + 1] = (CompilerDef) baseDefs[i]; + } + defaultProviders[0] = specificDef; + Vector cmdArgs = new Vector(); + // + // add command line arguments inherited from <cc> element + // any "extends" and finally the specific CompilerDef + CommandLineArgument[] commandArgs; + for (int i = defaultProviders.length - 1; i >= 0; i--) { + commandArgs = defaultProviders[i].getActiveProcessorArgs(); + for (int j = 0; j < commandArgs.length; j++) { + if (commandArgs[j].getLocation() == 0) { + args.addElement(commandArgs[j].getValue()); + } else { + cmdArgs.addElement(commandArgs[j]); + } + } + } + Vector params = new Vector(); + // + // add command line arguments inherited from <cc> element + // any "extends" and finally the specific CompilerDef + ProcessorParam[] paramArray; + for (int i = defaultProviders.length - 1; i >= 0; i--) { + paramArray = defaultProviders[i].getActiveProcessorParams(); + for (int j = 0; j < paramArray.length; j++) { + params.add(paramArray[j]); + } + } + paramArray = (ProcessorParam[]) (params + .toArray(new ProcessorParam[params.size()])); + boolean multithreaded = specificDef.getMultithreaded(defaultProviders, + 1); + boolean debug = specificDef.getDebug(baseDefs, 0); + boolean exceptions = specificDef.getExceptions(defaultProviders, 1); + Boolean rtti = specificDef.getRtti(defaultProviders, 1); + OptimizationEnum optimization = specificDef.getOptimization(defaultProviders, 1); + this.addImpliedArgs(args, debug, multithreaded, exceptions, linkType, rtti, optimization); + // + // add all appropriate defines and undefines + // + buildDefineArguments(defaultProviders, args); + // + // Want to have distinct set of arguments with relative + // path names for includes that are used to build + // the configuration identifier + // + Vector relativeArgs = (Vector) args.clone(); + // + // add all active include and sysincludes + // + StringBuffer includePathIdentifier = new StringBuffer(); + File baseDir = specificDef.getProject().getBaseDir(); + String baseDirPath; + try { + baseDirPath = baseDir.getCanonicalPath(); + } catch (IOException ex) { + baseDirPath = baseDir.toString(); + } + Vector includePath = new Vector(); + Vector sysIncludePath = new Vector(); + for (int i = defaultProviders.length - 1; i >= 0; i--) { + String[] incPath = defaultProviders[i].getActiveIncludePaths(); + for (int j = 0; j < incPath.length; j++) { + includePath.addElement(incPath[j]); + } + incPath = defaultProviders[i].getActiveSysIncludePaths(); + for (int j = 0; j < incPath.length; j++) { + sysIncludePath.addElement(incPath[j]); + } + } + File[] incPath = new File[includePath.size()]; + for (int i = 0; i < includePath.size(); i++) { + incPath[i] = new File((String) includePath.elementAt(i)); + } + File[] sysIncPath = new File[sysIncludePath.size()]; + for (int i = 0; i < sysIncludePath.size(); i++) { + sysIncPath[i] = new File((String) sysIncludePath.elementAt(i)); + } + addIncludes(baseDirPath, incPath, args, relativeArgs, + includePathIdentifier); + addIncludes(baseDirPath, sysIncPath, args, null, null); + StringBuffer buf = new StringBuffer(getIdentifier()); + for (int i = 0; i < relativeArgs.size(); i++) { + buf.append(relativeArgs.elementAt(i)); + buf.append(' '); + } + buf.setLength(buf.length() - 1); + String configId = buf.toString(); + int warnings = specificDef.getWarnings(defaultProviders, 0); + addWarningSwitch(args, warnings); + Enumeration argEnum = cmdArgs.elements(); + int endCount = 0; + while (argEnum.hasMoreElements()) { + CommandLineArgument arg = (CommandLineArgument) argEnum + .nextElement(); + switch (arg.getLocation()) { + case 1 : + args.addElement(arg.getValue()); + break; + case 2 : + endCount++; + break; + } + } + String[] endArgs = new String[endCount]; + argEnum = cmdArgs.elements(); + int index = 0; + while (argEnum.hasMoreElements()) { + CommandLineArgument arg = (CommandLineArgument) argEnum + .nextElement(); + if (arg.getLocation() == 2) { + endArgs[index++] = arg.getValue(); + } + } + String[] argArray = new String[args.size()]; + args.copyInto(argArray); + boolean rebuild = specificDef.getRebuild(baseDefs, 0); + File[] envIncludePath = getEnvironmentIncludePath(); + return new CommandLineCompilerConfiguration(this, configId, incPath, + sysIncPath, envIncludePath, includePathIdentifier.toString(), + argArray, paramArray, rebuild, endArgs); + } + protected int getArgumentCountPerInputFile() { + return 1; + } + protected final String getCommand() { + return command; + } + abstract protected void getDefineSwitch(StringBuffer buffer, String define, + String value); + protected abstract File[] getEnvironmentIncludePath(); + public String getIdentifier() { + if (identifier == null) { + if (identifierArg == null) { + identifier = getIdentifier(new String[]{command}, command); + } else { + identifier = getIdentifier( + new String[]{command, identifierArg}, command); + } + } + return identifier; + } + abstract protected String getIncludeDirSwitch(String source); + protected String getInputFileArgument(File outputDir, String filename, + int index) { + // + // if there is an embedded space, + // must enclose in quotes + if (filename.indexOf(' ') >= 0) { + StringBuffer buf = new StringBuffer("\""); + buf.append(filename); + buf.append("\""); + return buf.toString(); + } + return filename; + } + protected final boolean getLibtool() { + return libtool; + } + /** + * Obtains the same compiler, but with libtool set + * + * Default behavior is to ignore libtool + */ + public final CommandLineCompiler getLibtoolCompiler() { + if (libtoolCompiler != null) { + return libtoolCompiler; + } + return this; + } + abstract public int getMaximumCommandLength(); + protected int getMaximumInputFilesPerCommand() { + return Integer.MAX_VALUE; + } + protected int getTotalArgumentLengthForInputFile(File outputDir, + String inputFile) { + return inputFile.length() + 1; + } + abstract protected void getUndefineSwitch(StringBuffer buffer, String define); + /** + * This method is exposed so test classes can overload and test the + * arguments without actually spawning the compiler + */ + protected int runCommand(CCTask task, File workingDir, String[] cmdline) + throws BuildException { + return CUtil.runCommand(task, workingDir, cmdline, newEnvironment, env); + } + protected final void setCommand(String command) { + this.command = command; + } +} diff --git a/src/net/sf/antcontrib/cpptasks/compiler/CommandLineCompilerConfiguration.java b/src/net/sf/antcontrib/cpptasks/compiler/CommandLineCompilerConfiguration.java new file mode 100644 index 0000000..38492ea --- /dev/null +++ b/src/net/sf/antcontrib/cpptasks/compiler/CommandLineCompilerConfiguration.java @@ -0,0 +1,226 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import java.io.File; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CompilerParam; +import net.sf.antcontrib.cpptasks.DependencyInfo; +import net.sf.antcontrib.cpptasks.ProcessorParam; +import net.sf.antcontrib.cpptasks.VersionInfo; + +import org.apache.tools.ant.BuildException; +/** + * A configuration for a C++ compiler + * + * @author Curt Arnold + */ +public final class CommandLineCompilerConfiguration + implements + CompilerConfiguration { + private/* final */String[] args; + private/* final */CommandLineCompiler compiler; + private String[] endArgs; + // + // include path from environment variable not + // explicitly stated in Ant script + private/* final */File[] envIncludePath; + private String[] exceptFiles; + private/* final */String identifier; + private/* final */File[] includePath; + private/* final */String includePathIdentifier; + private boolean isPrecompiledHeaderGeneration; + private/* final */ProcessorParam[] params; + private/* final */boolean rebuild; + private/* final */File[] sysIncludePath; + public CommandLineCompilerConfiguration(CommandLineCompiler compiler, + String identifier, File[] includePath, File[] sysIncludePath, + File[] envIncludePath, String includePathIdentifier, String[] args, + ProcessorParam[] params, boolean rebuild, String[] endArgs) { + if (compiler == null) { + throw new NullPointerException("compiler"); + } + if (identifier == null) { + throw new NullPointerException("identifier"); + } + if (includePathIdentifier == null) { + throw new NullPointerException("includePathIdentifier"); + } + if (args == null) { + this.args = new String[0]; + } else { + this.args = (String[]) args.clone(); + } + if (includePath == null) { + this.includePath = new File[0]; + } else { + this.includePath = (File[]) includePath.clone(); + } + if (sysIncludePath == null) { + this.sysIncludePath = new File[0]; + } else { + this.sysIncludePath = (File[]) sysIncludePath.clone(); + } + if (envIncludePath == null) { + this.envIncludePath = new File[0]; + } else { + this.envIncludePath = (File[]) envIncludePath.clone(); + } + this.compiler = compiler; + this.params = (ProcessorParam[]) params.clone(); + this.rebuild = rebuild; + this.identifier = identifier; + this.includePathIdentifier = includePathIdentifier; + this.endArgs = (String[]) endArgs.clone(); + exceptFiles = null; + isPrecompiledHeaderGeneration = false; + } + public CommandLineCompilerConfiguration( + CommandLineCompilerConfiguration base, String[] additionalArgs, + String[] exceptFiles, boolean isPrecompileHeaderGeneration) { + compiler = base.compiler; + identifier = base.identifier; + rebuild = base.rebuild; + includePath = (File[]) base.includePath.clone(); + sysIncludePath = (File[]) base.sysIncludePath.clone(); + endArgs = (String[]) base.endArgs.clone(); + envIncludePath = (File[]) base.envIncludePath.clone(); + includePathIdentifier = base.includePathIdentifier; + if (exceptFiles != null) { + this.exceptFiles = (String[]) exceptFiles.clone(); + } + this.isPrecompiledHeaderGeneration = isPrecompileHeaderGeneration; + args = new String[base.args.length + additionalArgs.length]; + for (int i = 0; i < base.args.length; i++) { + args[i] = base.args[i]; + } + int index = base.args.length; + for (int i = 0; i < additionalArgs.length; i++) { + args[index++] = additionalArgs[i]; + } + } + public int bid(String inputFile) { + int compilerBid = compiler.bid(inputFile); + if (compilerBid > 0 && exceptFiles != null) { + for (int i = 0; i < exceptFiles.length; i++) { + if (inputFile.equals(exceptFiles[i])) { + return 0; + } + } + } + return compilerBid; + } + public void compile(CCTask task, File outputDir, String[] sourceFiles, + boolean relentless, ProgressMonitor monitor) throws BuildException { + if (monitor != null) { + monitor.start(this); + } + try { + compiler.compile(task, outputDir, sourceFiles, args, endArgs, + relentless, this, monitor); + if (monitor != null) { + monitor.finish(this, true); + } + } catch (BuildException ex) { + if (monitor != null) { + monitor.finish(this, false); + } + throw ex; + } + } + /** + * + * This method may be used to get two distinct compiler configurations, one + * for compiling the specified file and producing a precompiled header + * file, and a second for compiling other files using the precompiled + * header file. + * + * The last (preferrably only) include directive in the prototype file will + * be used to mark the boundary between pre-compiled and normally compiled + * headers. + * + * @param prototype + * A source file (for example, stdafx.cpp) that is used to build + * the precompiled header file. @returns null if precompiled + * headers are not supported or a two element array containing + * the precompiled header generation configuration and the + * consuming configuration + * + */ + public CompilerConfiguration[] createPrecompileConfigurations( + File prototype, String[] nonPrecompiledFiles) { + if (compiler instanceof PrecompilingCompiler) { + return ((PrecompilingCompiler) compiler) + .createPrecompileConfigurations(this, prototype, + nonPrecompiledFiles); + } + return null; + } + /** + * Returns a string representation of this configuration. Should be + * canonical so that equivalent configurations will have equivalent string + * representations + */ + public String getIdentifier() { + return identifier; + } + public String getIncludePathIdentifier() { + return includePathIdentifier; + } + public String[] getOutputFileNames(String inputFile, VersionInfo versionInfo) { + return compiler.getOutputFileNames(inputFile, versionInfo); + } + public CompilerParam getParam(String name) { + for (int i = 0; i < params.length; i++) { + if (name.equals(params[i].getName())) + return (CompilerParam) params[i]; + } + return null; + } + public ProcessorParam[] getParams() { + return params; + } + public boolean getRebuild() { + return rebuild; + } + public boolean isPrecompileGeneration() { + return isPrecompiledHeaderGeneration; + } + public DependencyInfo parseIncludes(CCTask task, File baseDir, File source) { + return compiler.parseIncludes(task, source, includePath, + sysIncludePath, envIncludePath, baseDir, + getIncludePathIdentifier()); + } + public String toString() { + return identifier; + } + public String[] getPreArguments() { + return (String[]) args.clone(); + } + public String[] getEndArguments() { + return (String[]) endArgs.clone(); + } + public File[] getIncludePath() { + return (File[]) includePath.clone(); + } + public Compiler getCompiler() { + return compiler; + } + public String getCommand() { + return compiler.getCommand(); + } +} diff --git a/src/net/sf/antcontrib/cpptasks/compiler/CommandLineFortranCompiler.java b/src/net/sf/antcontrib/cpptasks/compiler/CommandLineFortranCompiler.java new file mode 100644 index 0000000..7b0eed2 --- /dev/null +++ b/src/net/sf/antcontrib/cpptasks/compiler/CommandLineFortranCompiler.java @@ -0,0 +1,42 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import java.io.File; + +import net.sf.antcontrib.cpptasks.parser.FortranParser; +import net.sf.antcontrib.cpptasks.parser.Parser; + +import org.apache.tools.ant.types.Environment; +/** + * An abstract Compiler implementation which uses an external program to + * perform the compile. + * + * @author Curt Arnold + */ +public abstract class CommandLineFortranCompiler extends CommandLineCompiler { + protected CommandLineFortranCompiler(String command, String identifierArg, + String[] sourceExtensions, String[] headerExtensions, + String outputSuffix, boolean libtool, + CommandLineFortranCompiler libtoolCompiler, boolean newEnvironment, + Environment env) { + super(command, identifierArg, sourceExtensions, headerExtensions, + outputSuffix, libtool, libtoolCompiler, newEnvironment, env); + } + protected Parser createParser(File source) { + return new FortranParser(); + } +} diff --git a/src/net/sf/antcontrib/cpptasks/compiler/CommandLineLinker.java b/src/net/sf/antcontrib/cpptasks/compiler/CommandLineLinker.java new file mode 100644 index 0000000..f9e4761 --- /dev/null +++ b/src/net/sf/antcontrib/cpptasks/compiler/CommandLineLinker.java @@ -0,0 +1,406 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Enumeration; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.LinkerDef; +import net.sf.antcontrib.cpptasks.ProcessorDef; +import net.sf.antcontrib.cpptasks.ProcessorParam; +import net.sf.antcontrib.cpptasks.types.CommandLineArgument; +import net.sf.antcontrib.cpptasks.types.LibrarySet; +import net.sf.antcontrib.cpptasks.TargetDef; +import net.sf.antcontrib.cpptasks.VersionInfo; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.types.Environment; + + +/** + * An abstract Linker implementation that performs the link via an external + * command. + * + * @author Adam Murdoch + */ +public abstract class CommandLineLinker extends AbstractLinker +{ + private String command; + private Environment env = null; + private String identifier; + private String identifierArg; + private boolean isLibtool; + private String[] librarySets; + private CommandLineLinker libtoolLinker; + private boolean newEnvironment = false; + private String outputSuffix; + + + /** Creates a comand line linker invocation */ + public CommandLineLinker(String command, + String identifierArg, + String[] extensions, + String[] ignoredExtensions, String outputSuffix, + boolean isLibtool, CommandLineLinker libtoolLinker) + { + super(extensions, ignoredExtensions); + this.command = command; + this.identifierArg = identifierArg; + this.outputSuffix = outputSuffix; + this.isLibtool = isLibtool; + this.libtoolLinker = libtoolLinker; + } + protected abstract void addBase(long base, Vector args); + + protected abstract void addFixed(Boolean fixed, Vector args); + + abstract protected void addImpliedArgs(boolean debug, + LinkType linkType, Vector args); + protected abstract void addIncremental(boolean incremental, Vector args); + + // + // Windows processors handle these through file list + // + protected String[] addLibrarySets(CCTask task, LibrarySet[] libsets, Vector preargs, + Vector midargs, Vector endargs) { + return null; + } + protected abstract void addMap(boolean map, Vector args); + protected abstract void addStack(int stack, Vector args); + protected abstract void addEntry(String entry, Vector args); + + protected LinkerConfiguration createConfiguration( + CCTask task, + LinkType linkType, + ProcessorDef[] baseDefs, LinkerDef specificDef, TargetDef targetPlatform, + VersionInfo versionInfo) { + + Vector preargs = new Vector(); + Vector midargs = new Vector(); + Vector endargs = new Vector(); + Vector[] args = new Vector[] { preargs, midargs, endargs }; + + LinkerDef[] defaultProviders = new LinkerDef[baseDefs.length+1]; + defaultProviders[0] = specificDef; + for(int i = 0; i < baseDefs.length; i++) { + defaultProviders[i+1] = (LinkerDef) baseDefs[i]; + } + // + // add command line arguments inherited from <cc> element + // any "extends" and finally the specific CompilerDef + CommandLineArgument[] commandArgs; + for(int i = defaultProviders.length-1; i >= 0; i--) { + commandArgs = defaultProviders[i].getActiveProcessorArgs(); + for(int j = 0; j < commandArgs.length; j++) { + args[commandArgs[j].getLocation()]. + addElement(commandArgs[j].getValue()); + } + } + + Vector params = new Vector(); + // + // add command line arguments inherited from <cc> element + // any "extends" and finally the specific CompilerDef + ProcessorParam[] paramArray; + for (int i = defaultProviders.length - 1; i >= 0; i--) { + paramArray = defaultProviders[i].getActiveProcessorParams(); + for (int j = 0; j < paramArray.length; j++) { + params.add(paramArray[j]); + } + } + + paramArray = (ProcessorParam[])(params.toArray(new ProcessorParam[params.size()])); + + boolean debug = specificDef.getDebug(baseDefs,0); + + + String startupObject = getStartupObject(linkType); + + addImpliedArgs(debug, linkType, preargs); + addIncremental(specificDef.getIncremental(defaultProviders,1), preargs); + addFixed(specificDef.getFixed(defaultProviders,1), preargs); + addMap(specificDef.getMap(defaultProviders,1), preargs); + addBase(specificDef.getBase(defaultProviders,1), preargs); + addStack(specificDef.getStack(defaultProviders,1), preargs); + addEntry(specificDef.getEntry(defaultProviders, 1), preargs); + + String[] libnames = null; + LibrarySet[] libsets = specificDef.getActiveLibrarySets(defaultProviders,1); + if (libsets.length > 0) { + libnames = addLibrarySets(task, libsets, preargs, midargs, endargs); + } + + StringBuffer buf = new StringBuffer(getIdentifier()); + for (int i = 0; i < 3; i++) { + Enumeration argenum = args[i].elements(); + while (argenum.hasMoreElements()) { + buf.append(' '); + buf.append(argenum.nextElement().toString()); + } + } + String configId = buf.toString(); + + String[][] options = new String[][] { + new String[args[0].size() + args[1].size()], + new String[args[2].size()] }; + args[0].copyInto(options[0]); + int offset = args[0].size(); + for (int i = 0; i < args[1].size(); i++) { + options[0][i+offset] = (String) args[1].elementAt(i); + } + args[2].copyInto(options[1]); + + + boolean rebuild = specificDef.getRebuild(baseDefs,0); + boolean map = specificDef.getMap(defaultProviders,1); + + //task.log("libnames:"+libnames.length, Project.MSG_VERBOSE); + return new CommandLineLinkerConfiguration(this,configId,options, + paramArray, + rebuild,map, debug,libnames, startupObject); + } + + /** + * Allows drived linker to decorate linker option. + * Override by GccLinker to prepend a "-Wl," to + * pass option to through gcc to linker. + * + * @param buf buffer that may be used and abused in the decoration process, + * must not be null. + * @param arg linker argument + */ + protected String decorateLinkerOption(StringBuffer buf, String arg) { + return arg; + } + + protected final String getCommand() { + return command; + } + protected abstract String getCommandFileSwitch(String commandFile); + + + public String getIdentifier() { + if(identifier == null) { + if (identifierArg == null) { + identifier = getIdentifier(new String[] { command }, command); + } else { + identifier = getIdentifier(new String[] { command, identifierArg }, + command); + } + } + return identifier; + } + public final CommandLineLinker getLibtoolLinker() { + if (libtoolLinker != null) { + return libtoolLinker; + } + return this; + } + protected abstract int getMaximumCommandLength(); + + public String[] getOutputFileNames(String baseName, VersionInfo versionInfo) { + return new String[] { baseName + outputSuffix }; + } + + protected String[] getOutputFileSwitch(CCTask task, String outputFile) { + return getOutputFileSwitch(outputFile); + } + protected abstract String[] getOutputFileSwitch(String outputFile); + protected String getStartupObject(LinkType linkType) { + return null; + } + + /** + * Performs a link using a command line linker + * + */ + public void link(CCTask task, + File outputFile, + String[] sourceFiles, + CommandLineLinkerConfiguration config) + throws BuildException + { + File parentDir = new File(outputFile.getParent()); + String parentPath; + try { + parentPath = parentDir.getCanonicalPath(); + } catch(IOException ex) { + parentPath = parentDir.getAbsolutePath(); + } + String[] execArgs = prepareArguments(task, parentPath,outputFile.getName(), + sourceFiles, config); + int commandLength = 0; + for(int i = 0; i < execArgs.length; i++) { + commandLength += execArgs[i].length() + 1; + } + + // + // if command length exceeds maximum + // then create a temporary + // file containing everything but the command name + if(commandLength >= this.getMaximumCommandLength()) { + try { + execArgs = prepareResponseFile(outputFile,execArgs); + } + catch(IOException ex) { + throw new BuildException(ex); + } + } + + int retval = runCommand(task,parentDir,execArgs); + // + // if the process returned a failure code then + // throw an BuildException + // + if(retval != 0) { + // + // construct the exception + // + throw new BuildException(this.getCommand() + " failed with return code " + retval, task.getLocation()); + } + + } + + + /** + * Prepares argument list for exec command. Will return null + * if command line would exceed allowable command line buffer. + * + * @param outputFile linker output file + * @param sourceFiles linker input files (.obj, .o, .res) + * @param args linker arguments + * @return arguments for runTask + */ + protected String[] prepareArguments( + CCTask task, + String outputDir, + String outputFile, + String[] sourceFiles, + CommandLineLinkerConfiguration config) { + + String[] preargs = config.getPreArguments(); + String[] endargs = config.getEndArguments(); + String outputSwitch[] = getOutputFileSwitch(task, outputFile); + int allArgsCount = preargs.length + 1 + outputSwitch.length + + sourceFiles.length + endargs.length; + if (isLibtool) { + allArgsCount++; + } + String[] allArgs = new String[allArgsCount]; + int index = 0; + if (isLibtool) { + allArgs[index++] = "libtool"; + } + allArgs[index++] = this.getCommand(); + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < preargs.length; i++) { + allArgs[index++] = decorateLinkerOption(buf, preargs[i]); + } + for (int i = 0; i < outputSwitch.length; i++) { + allArgs[index++] = outputSwitch[i]; + } + for (int i = 0; i < sourceFiles.length; i++) { + allArgs[index++] = prepareFilename(buf,outputDir,sourceFiles[i]); + } + for (int i = 0; i < endargs.length; i++) { + allArgs[index++] = decorateLinkerOption(buf, endargs[i]); + } + return allArgs; + } + + /** + * Processes filename into argument form + * + */ + protected String prepareFilename(StringBuffer buf, + String outputDir, String sourceFile) { + String relativePath = CUtil.getRelativePath(outputDir, + new File(sourceFile)); + return quoteFilename(buf,relativePath); + } + + /** + * Prepares argument list to execute the linker using a + * response file. + * + * @param outputFile linker output file + * @param args output of prepareArguments + * @return arguments for runTask + */ + protected String[] prepareResponseFile(File outputFile,String[] args) throws IOException + { + String baseName = outputFile.getName(); + File commandFile = new File(outputFile.getParent(),baseName + ".rsp"); + FileWriter writer = new FileWriter(commandFile); + int execArgCount = 1; + if (isLibtool) { + execArgCount++; + } + String[] execArgs = new String[execArgCount+1]; + for (int i = 0; i < execArgCount; i++) { + execArgs[i] = args[i]; + } + execArgs[execArgCount] = getCommandFileSwitch(commandFile.toString()); + for(int i = execArgCount; i < args.length; i++) { + // + // if embedded space and not quoted then + // quote argument + if (args[i].indexOf(" ") >= 0 && args[i].charAt(0) != '\"') { + writer.write('\"'); + writer.write(args[i]); + writer.write("\"\n"); + } else { + writer.write(args[i]); + writer.write('\n'); + } + } + writer.close(); + return execArgs; + } + + + protected String quoteFilename(StringBuffer buf,String filename) { + if(filename.indexOf(' ') >= 0) { + buf.setLength(0); + buf.append('\"'); + buf.append(filename); + buf.append('\"'); + return buf.toString(); + } + return filename; + } + + /** + * This method is exposed so test classes can overload + * and test the arguments without actually spawning the + * compiler + */ + protected int runCommand(CCTask task, File workingDir,String[] cmdline) + throws BuildException { + return CUtil.runCommand(task,workingDir,cmdline, newEnvironment, env); + } + + protected final void setCommand(String command) { + this.command = command; + } + +} diff --git a/src/net/sf/antcontrib/cpptasks/compiler/CommandLineLinkerConfiguration.java b/src/net/sf/antcontrib/cpptasks/compiler/CommandLineLinkerConfiguration.java new file mode 100644 index 0000000..f0aad67 --- /dev/null +++ b/src/net/sf/antcontrib/cpptasks/compiler/CommandLineLinkerConfiguration.java @@ -0,0 +1,128 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.LinkerParam; +import net.sf.antcontrib.cpptasks.ProcessorParam; +import net.sf.antcontrib.cpptasks.TargetInfo; +import net.sf.antcontrib.cpptasks.VersionInfo; + +import org.apache.tools.ant.BuildException; +/** + * A configuration for a command line linker + * + * @author Curt Arnold + */ +public final class CommandLineLinkerConfiguration + implements + LinkerConfiguration { + private/* final */String[][] args; + private/* final */String identifier; + private String[] libraryNames; + private/* final */CommandLineLinker linker; + private/* final */boolean map; + private/* final */ProcessorParam[] params; + private/* final */boolean rebuild; + private boolean debug; + private String startupObject; + public CommandLineLinkerConfiguration(CommandLineLinker linker, + String identifier, String[][] args, ProcessorParam[] params, + boolean rebuild, boolean map, boolean debug, String[] libraryNames, + String startupObject) { + if (linker == null) { + throw new NullPointerException("linker"); + } + if (args == null) { + throw new NullPointerException("args"); + } else { + this.args = (String[][]) args.clone(); + } + this.linker = linker; + this.params = (ProcessorParam[]) params.clone(); + this.rebuild = rebuild; + this.identifier = identifier; + this.map = map; + this.debug = debug; + if (libraryNames == null) { + this.libraryNames = new String[0]; + } else { + this.libraryNames = (String[]) libraryNames.clone(); + } + this.startupObject = startupObject; + } + public int bid(String filename) { + return linker.bid(filename); + } + public String[] getEndArguments() { + String[] clone = (String[]) args[1].clone(); + return clone; + } + /** + * Returns a string representation of this configuration. Should be + * canonical so that equivalent configurations will have equivalent string + * representations + */ + public String getIdentifier() { + return identifier; + } + public String[] getLibraryNames() { + String[] clone = (String[]) libraryNames.clone(); + return clone; + } + public boolean getMap() { + return map; + } + public String[] getOutputFileNames(String inputFile, VersionInfo versionInfo) { + return linker.getOutputFileNames(inputFile, versionInfo); + } + public LinkerParam getParam(String name) { + for (int i = 0; i < params.length; i++) { + if (name.equals(params[i].getName())) + return (LinkerParam) params[i]; + } + return null; + } + public ProcessorParam[] getParams() { + return params; + } + public String[] getPreArguments() { + String[] clone = (String[]) args[0].clone(); + return clone; + } + public boolean getRebuild() { + return rebuild; + } + public String getStartupObject() { + return startupObject; + } + public void link(CCTask task, TargetInfo linkTarget) throws BuildException { + // + // AllSourcePath's include any syslibsets + // + String[] sourcePaths = linkTarget.getAllSourcePaths(); + linker.link(task, linkTarget.getOutput(), sourcePaths, this); + } + public String toString() { + return identifier; + } + public Linker getLinker() { + return linker; + } + public boolean isDebug() { + return debug; + } +} diff --git a/src/net/sf/antcontrib/cpptasks/compiler/Compiler.java b/src/net/sf/antcontrib/cpptasks/compiler/Compiler.java new file mode 100644 index 0000000..48bc190 --- /dev/null +++ b/src/net/sf/antcontrib/cpptasks/compiler/Compiler.java @@ -0,0 +1,24 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +/** + * A compiler. + * + * @author Adam Murdoch + */ +public interface Compiler extends Processor { +} diff --git a/src/net/sf/antcontrib/cpptasks/compiler/CompilerConfiguration.java b/src/net/sf/antcontrib/cpptasks/compiler/CompilerConfiguration.java new file mode 100644 index 0000000..6aba345 --- /dev/null +++ b/src/net/sf/antcontrib/cpptasks/compiler/CompilerConfiguration.java @@ -0,0 +1,64 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import java.io.File; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CompilerParam; +import net.sf.antcontrib.cpptasks.DependencyInfo; + +import org.apache.tools.ant.BuildException; +/** + * A configuration for a compiler + * + * @author Curt Arnold + */ +public interface CompilerConfiguration extends ProcessorConfiguration { + void compile(CCTask task, File outputDir, String[] sourceFiles, + boolean relentless, ProgressMonitor monitor) throws BuildException; + /** + * + * This method may be used to get two distinct compiler configurations, one + * for compiling the specified file and producing a precompiled header + * file, and a second for compiling other files using the precompiled + * header file. + * + * The last (preferrably only) include directive in the prototype file will + * be used to mark the boundary between pre-compiled and normally compiled + * headers. + * + * @param prototype + * A source file (for example, stdafx.cpp) that is used to build + * the precompiled header file. @returns null if precompiled + * headers are not supported or a two element array containing + * the precompiled header generation configuration and the + * consuming configuration + * + */ + CompilerConfiguration[] createPrecompileConfigurations(File prototype, + String[] nonPrecompiledFiles); + /** + * Returns an digest for the include path for the configuration. + * + * This is used to determine if cached dependency information is invalid + * because the include paths have changed + */ + String getIncludePathIdentifier(); + public CompilerParam getParam(String name); + boolean isPrecompileGeneration(); + DependencyInfo parseIncludes(CCTask task, File baseDir, File source); +} diff --git a/src/net/sf/antcontrib/cpptasks/compiler/LinkType.java b/src/net/sf/antcontrib/cpptasks/compiler/LinkType.java new file mode 100644 index 0000000..910c41a --- /dev/null +++ b/src/net/sf/antcontrib/cpptasks/compiler/LinkType.java @@ -0,0 +1,151 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import net.sf.antcontrib.cpptasks.OutputTypeEnum; +import net.sf.antcontrib.cpptasks.SubsystemEnum; +/** + * This class represents the target platform for the compile and link step. The + * name is an anachronism and should be changed. + * + * @author Curt Arnold + */ +public class LinkType { + private OutputTypeEnum outputType = new OutputTypeEnum(); + private boolean staticRuntime = false; + private SubsystemEnum subsystem = new SubsystemEnum(); + /** + * Constructor + * + * By default, an gui executable with a dynamically linked runtime + * + */ + public LinkType() { + } + /** + * Gets whether the link should produce an executable + * + * @return boolean + */ + public boolean isExecutable() { + String value = outputType.getValue(); + return value.equals("executable"); + } + /** + * Gets whether the link should produce a plugin module. + * + * @return boolean + */ + public boolean isPluginModule() { + String value = outputType.getValue(); + return value.equals("plugin"); + } + /** + * Gets whether the link should produce a shared library. + * + * @return boolean + */ + public boolean isSharedLibrary() { + String value = outputType.getValue(); + return value.equals("shared") || value.equals("plugin"); + } + /** + * Gets whether the link should produce a static library. + * + * @return boolean + */ + public boolean isStaticLibrary() { + String value = outputType.getValue(); + return value.equals("static"); + } + /** + * Gets whether the module should use a statically linked runtime library. + * + * @return boolean + */ + public boolean isStaticRuntime() { + return staticRuntime; + } + /** + * Gets whether the link should produce a module for a console subsystem. + * + * @return boolean + */ + public boolean isSubsystemConsole() { + String value = subsystem.getValue(); + return value.equals("console"); + } + /** + * Gets whether the link should produce a module for a graphical user + * interface subsystem. + * + * @return boolean + */ + public boolean isSubsystemGUI() { + String value = subsystem.getValue(); + return value.equals("gui"); + } + /** + * Sets the output type (execuable, shared, etc). + * + * @param outputType, + * may not be null + */ + public void setOutputType(OutputTypeEnum outputType) { + if (outputType == null) { + throw new IllegalArgumentException("outputType"); + } + this.outputType = outputType; + } + + /** + * Gets the output type. + * @return output type + */ + public String getOutputType() { + return outputType.getValue(); + } + + /** + * Requests use of a static runtime library. + * + * @param staticRuntime + * if true, use static runtime library if possible. + */ + public void setStaticRuntime(boolean staticRuntime) { + this.staticRuntime = staticRuntime; + } + /** + * Sets the subsystem (gui, console, etc). + * + * @param subsystem + * subsystem, may not be null + */ + public void setSubsystem(SubsystemEnum subsystem) { + if (subsystem == null) { + throw new IllegalArgumentException("subsystem"); + } + this.subsystem = subsystem; + } + + /** + * Get subsystem name. + * @return subsystem name + */ + public String getSubsystem() { + return subsystem.getValue(); + } +} diff --git a/src/net/sf/antcontrib/cpptasks/compiler/Linker.java b/src/net/sf/antcontrib/cpptasks/compiler/Linker.java new file mode 100644 index 0000000..672a0e3 --- /dev/null +++ b/src/net/sf/antcontrib/cpptasks/compiler/Linker.java @@ -0,0 +1,80 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import java.io.File; +import java.io.IOException; + +import net.sf.antcontrib.cpptasks.TargetMatcher; +import net.sf.antcontrib.cpptasks.VersionInfo; +import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum; + +/** + * A linker for executables, and static and dynamic libraries. + * + * @author Adam Murdoch + */ +public interface Linker extends Processor { + /** + * Extracts the significant part of a library name to ensure there aren't + * collisions + */ + String getLibraryKey(File libname); + /** + * returns the library path for the linker + */ + File[] getLibraryPath(); + /** + * Returns a set of filename patterns corresponding to library names. + * + * For example, "advapi32" would be expanded to "advapi32.dll" by + * DevStudioLinker and to "libadvapi32.a" and "libadvapi32.so" by + * GccLinker. + * + * @param libnames + * array of library names + */ + String[] getLibraryPatterns(String[] libnames, LibraryTypeEnum libraryType); + /** + * Gets the linker for the specified link type. + * + * @return appropriate linker or null, will return this if this linker can + * handle the specified link type + */ + Linker getLinker(LinkType linkType); + /** + * Returns true if the linker is case-sensitive + */ + boolean isCaseSensitive(); + + /** + * Adds source or object files to the bidded fileset to + * support version information. + * + * @param versionInfo version information + * @param linkType link type + * @param isDebug true if debug build + * @param executableName name of generated executable + * @param objDir directory for generated files + * @param matcher bidded fileset + */ + void addVersionFiles(final VersionInfo versionInfo, + final LinkType linkType, + final File outputFile, + final boolean isDebug, + final File objDir, + final TargetMatcher matcher) throws IOException; +} diff --git a/src/net/sf/antcontrib/cpptasks/compiler/LinkerConfiguration.java b/src/net/sf/antcontrib/cpptasks/compiler/LinkerConfiguration.java new file mode 100644 index 0000000..ff7ac5d --- /dev/null +++ b/src/net/sf/antcontrib/cpptasks/compiler/LinkerConfiguration.java @@ -0,0 +1,33 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.LinkerParam; +import net.sf.antcontrib.cpptasks.TargetInfo; + +import org.apache.tools.ant.BuildException; +/** + * A configuration for a linker + * + * @author Curt Arnold + */ +public interface LinkerConfiguration extends ProcessorConfiguration { + public LinkerParam getParam(String name); + void link(CCTask task, TargetInfo linkTarget) throws BuildException; + Linker getLinker(); + boolean isDebug(); +} diff --git a/src/net/sf/antcontrib/cpptasks/compiler/PrecompilingCommandLineCCompiler.java b/src/net/sf/antcontrib/cpptasks/compiler/PrecompilingCommandLineCCompiler.java new file mode 100644 index 0000000..2af1a68 --- /dev/null +++ b/src/net/sf/antcontrib/cpptasks/compiler/PrecompilingCommandLineCCompiler.java @@ -0,0 +1,43 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import java.io.File; + +import net.sf.antcontrib.cpptasks.parser.CParser; +import net.sf.antcontrib.cpptasks.parser.Parser; + +import org.apache.tools.ant.types.Environment; +/** + * A command line C compiler that can utilize precompilation of header files + * + * @author Curt Arnold + */ +public abstract class PrecompilingCommandLineCCompiler + extends + PrecompilingCommandLineCompiler { + protected PrecompilingCommandLineCCompiler(String command, + String identifierArg, String[] sourceExtensions, + String[] headerExtensions, String outputSuffix, boolean libtool, + PrecompilingCommandLineCCompiler libtoolCompiler, + boolean newEnvironment, Environment env) { + super(command, identifierArg, sourceExtensions, headerExtensions, + outputSuffix, libtool, libtoolCompiler, newEnvironment, env); + } + protected Parser createParser(File source) { + return new CParser(); + } +} diff --git a/src/net/sf/antcontrib/cpptasks/compiler/PrecompilingCommandLineCompiler.java b/src/net/sf/antcontrib/cpptasks/compiler/PrecompilingCommandLineCompiler.java new file mode 100644 index 0000000..3b66597 --- /dev/null +++ b/src/net/sf/antcontrib/cpptasks/compiler/PrecompilingCommandLineCompiler.java @@ -0,0 +1,104 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; + +import net.sf.antcontrib.cpptasks.parser.Parser; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.types.Environment; +/** + * A command line C compiler that can utilize precompilation of header files + * + * @author Curt Arnold + */ +public abstract class PrecompilingCommandLineCompiler + extends + CommandLineCompiler implements PrecompilingCompiler { + protected PrecompilingCommandLineCompiler(String command, + String identifierArg, String[] sourceExtensions, + String[] headerExtensions, String outputSuffix, boolean libtool, + PrecompilingCommandLineCompiler libtoolCompiler, + boolean newEnvironment, Environment env) { + super(command, identifierArg, sourceExtensions, headerExtensions, + outputSuffix, libtool, libtoolCompiler, newEnvironment, env); + } + /** + * + * This method may be used to get two distinct compiler configurations, one + * for compiling the specified file and producing a precompiled header + * file, and a second for compiling other files using the precompiled + * header file. + * + * The last (preferrably only) include directive in the prototype file will + * be used to mark the boundary between pre-compiled and normally compiled + * headers. + * + * @param config + * base configuration + * @param prototype + * A source file (for example, stdafx.cpp) that is used to build + * the precompiled header file. @returns null if precompiled + * headers are not supported or a two element array containing + * the precompiled header generation configuration and the + * consuming configuration + * + */ + public CompilerConfiguration[] createPrecompileConfigurations( + CompilerConfiguration config, File prototype, String[] exceptFiles) { + // + // cast should success or someone is passing us a configuration + // that was prepared by another processor + // + CommandLineCompilerConfiguration cmdLineConfig = (CommandLineCompilerConfiguration) config; + // + // parse prototype file to determine last header + // + Parser parser = createParser(prototype); + String[] includes; + try { + Reader reader = new BufferedReader(new FileReader(prototype)); + parser.parse(reader); + includes = parser.getIncludes(); + } catch (IOException ex) { + throw new BuildException( + "Error parsing precompiled header protoype: " + + prototype.toString() + ":" + ex.toString()); + } + if (includes.length == 0) { + throw new BuildException("Precompiled header prototype: " + + prototype.toString() + + " does not contain any include directives."); + } + CompilerConfiguration[] configs = new CompilerConfiguration[2]; + configs[0] = createPrecompileGeneratingConfig(cmdLineConfig, prototype, + includes[0]); + configs[1] = createPrecompileUsingConfig(cmdLineConfig, prototype, + includes[0], exceptFiles); + return configs; + } + abstract protected CompilerConfiguration createPrecompileGeneratingConfig( + CommandLineCompilerConfiguration baseConfig, File prototype, + String lastInclude); + abstract protected CompilerConfiguration createPrecompileUsingConfig( + CommandLineCompilerConfiguration baseConfig, File prototype, + String lastInclude, String[] exceptFiles); +} diff --git a/src/net/sf/antcontrib/cpptasks/compiler/PrecompilingCompiler.java b/src/net/sf/antcontrib/cpptasks/compiler/PrecompilingCompiler.java new file mode 100644 index 0000000..f707dc5 --- /dev/null +++ b/src/net/sf/antcontrib/cpptasks/compiler/PrecompilingCompiler.java @@ -0,0 +1,49 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import java.io.File; +/** + * A compiler that can utilize precompilation of header files + * + * @author Curt Arnold + */ +public interface PrecompilingCompiler { + /** + * + * This method may be used to get two distinct compiler configurations, one + * for compiling the specified file and producing a precompiled header + * file, and a second for compiling other files using the precompiled + * header file. + * + * The last (preferrably only) include directive in the prototype file will + * be used to mark the boundary between pre-compiled and normally compiled + * headers. + * + * @param config + * base configuration + * @param prototype + * A source file (for example, stdafx.cpp) that is used to build + * the precompiled header file. @returns null if precompiled + * headers are not supported or a two element array containing + * the precompiled header generation configuration and the + * consuming configuration + * + */ + CompilerConfiguration[] createPrecompileConfigurations( + CompilerConfiguration config, File prototype, + String[] nonPrecompiledFiles); +} diff --git a/src/net/sf/antcontrib/cpptasks/compiler/Processor.java b/src/net/sf/antcontrib/cpptasks/compiler/Processor.java new file mode 100644 index 0000000..d6513f7 --- /dev/null +++ b/src/net/sf/antcontrib/cpptasks/compiler/Processor.java @@ -0,0 +1,75 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.ProcessorDef; +import net.sf.antcontrib.cpptasks.TargetDef; +import net.sf.antcontrib.cpptasks.VersionInfo; + +import org.apache.tools.ant.types.Environment; +/** + * A processor. Base interface for Compiler and Linker + * + * @author Curt Arnold + */ +public interface Processor { + /** + * Returns a bid indicating the desire of this compiler to process the + * file. + * + * @param inputFile + * input file + * @return 0 = no interest, 100 = high interest + */ + int bid(String inputFile); + Processor changeEnvironment(boolean newEnvironment, Environment env); + /** + * Returns the compiler configuration for <cc>or <compiler>element. + * + * @param defaultProviders + * When specificConfig corresponds to a <compiler>or linker + * element, defaultProvider will be a zero to two element array. + * If there is an extends attribute, the first element will be + * the referenced ProcessorDef, unless inherit = false, the last + * element will be the containing <cc>element + * @param specificConfig + * A <cc>or <compiler>element. + * @return resulting configuration + */ + ProcessorConfiguration createConfiguration(CCTask task, LinkType linkType, + ProcessorDef[] defaultProviders, ProcessorDef specificConfig, + TargetDef targetPlatform, VersionInfo versionInfo); + /** + * Retrieve an identifier that identifies the specific version of the + * compiler. Compilers with the same identifier should produce the same + * output files for the same input files and command line switches. + */ + String getIdentifier(); + /** + * Gets the linker that is associated with this processors + */ + Linker getLinker(LinkType type); + /** + * Output file name (no path components) corresponding to source file + * + * @param inputFile + * input file + * @return output file name or null if no output file or name not + * determined by input file + */ + String[] getOutputFileNames(String inputFile, VersionInfo versionInfo); +} diff --git a/src/net/sf/antcontrib/cpptasks/compiler/ProcessorConfiguration.java b/src/net/sf/antcontrib/cpptasks/compiler/ProcessorConfiguration.java new file mode 100644 index 0000000..870fb33 --- /dev/null +++ b/src/net/sf/antcontrib/cpptasks/compiler/ProcessorConfiguration.java @@ -0,0 +1,54 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import net.sf.antcontrib.cpptasks.ProcessorParam; +import net.sf.antcontrib.cpptasks.VersionInfo; + +/** + * A configuration for a C++ compiler, linker or other processor + * + * @author Curt Arnold + */ +public interface ProcessorConfiguration { + /** + * An indication of how much this compiler would like to process this file + * + * @return 0 is no interest to process, 100 is strong interest to process + */ + int bid(String filename); + /** + * Returns a string representation of this configuration. Should be + * canonical so that equivalent configurations will have equivalent string + * representations + */ + String getIdentifier(); + /** + * Output file name (no path components) corresponding to source file + * + * @param inputFile + * input file + * @return output file names or zero-length array if no output file or name not + * determined by input file + */ + String[] getOutputFileNames(String inputFile, VersionInfo versionInfo); + ProcessorParam[] getParams(); + /** + * If true, all files using this configuration should be rebuilt and any + * existing output files should be ignored + */ + boolean getRebuild(); +} diff --git a/src/net/sf/antcontrib/cpptasks/compiler/ProgressMonitor.java b/src/net/sf/antcontrib/cpptasks/compiler/ProgressMonitor.java new file mode 100644 index 0000000..9949856 --- /dev/null +++ b/src/net/sf/antcontrib/cpptasks/compiler/ProgressMonitor.java @@ -0,0 +1,31 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +/** + * Interface to receive notification of compile progress + * + * @author Curt Arnold + */ +public interface ProgressMonitor { + public void finish(ProcessorConfiguration config, boolean normal); + /** + * Called to notify monitor of progress + * + */ + void progress(String[] sources); + public void start(ProcessorConfiguration config); +} |