diff options
Diffstat (limited to 'src/main/java/net/sf/antcontrib/cpptasks/gcc')
21 files changed, 3889 insertions, 0 deletions
diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/AbstractArLibrarian.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/AbstractArLibrarian.java new file mode 100644 index 0000000..2e8d4af --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/AbstractArLibrarian.java @@ -0,0 +1,107 @@ +/* + * + * 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.gcc; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinker; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinkerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.VersionInfo; +import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum; + +import org.apache.tools.ant.BuildException; +/** + * Adapter for the "ar" tool + * + * @author Adam Murdoch + * @author Curt Arnold + */ +public abstract class AbstractArLibrarian extends CommandLineLinker { + private/* final */ + String outputPrefix; + protected AbstractArLibrarian(String command, String identificationArg, + String[] inputExtensions, String[] ignoredExtensions, + String outputPrefix, String outputExtension, boolean isLibtool, + AbstractArLibrarian libtoolLibrarian) { + super(command, identificationArg, inputExtensions, ignoredExtensions, + outputExtension, isLibtool, libtoolLibrarian); + this.outputPrefix = outputPrefix; + } + public void addBase(long base, Vector args) { + } + public void addFixed(Boolean fixed, Vector args) { + } + public void addImpliedArgs(boolean debug, LinkType linkType, Vector args) { + } + public void addIncremental(boolean incremental, Vector args) { + } + public void addMap(boolean map, Vector args) { + } + public void addStack(int stack, Vector args) { + } + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addEntry(int, java.util.Vector) + */ + protected void addEntry(String entry, Vector args) { + } + + public String getCommandFileSwitch(String commandFile) { + return null; + } + public File[] getLibraryPath() { + return new File[0]; + } + public String[] getLibraryPatterns(String[] libnames, LibraryTypeEnum libType) { + return new String[0]; + } + public int getMaximumCommandLength() { + return Integer.MAX_VALUE; + } + public String[] getOutputFileNames(String baseName, VersionInfo versionInfo) { + String[] baseNames = super.getOutputFileNames(baseName, versionInfo); + if (outputPrefix.length() > 0) { + for(int i = 0; i < baseNames.length; i++) { + baseNames[i] = outputPrefix + baseNames[i]; + } + } + return baseNames; + } + public String[] getOutputFileSwitch(String outputFile) { + return GccProcessor.getOutputFileSwitch("rvs", outputFile); + } + public boolean isCaseSensitive() { + return true; + } + public void link(CCTask task, File outputFile, String[] sourceFiles, + CommandLineLinkerConfiguration config) throws BuildException { + // + // if there is an existing library then + // we must delete it before executing "ar" + if (outputFile.exists()) { + if (!outputFile.delete()) { + throw new BuildException("Unable to delete " + + outputFile.getAbsolutePath()); + } + } + // + // delegate to CommandLineLinker + // + super.link(task, outputFile, sourceFiles, config); + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/AbstractLdLinker.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/AbstractLdLinker.java new file mode 100644 index 0000000..ffeb6b2 --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/AbstractLdLinker.java @@ -0,0 +1,333 @@ +/* + * + * 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.gcc; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinker; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinkerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.VersionInfo; +import net.sf.antcontrib.cpptasks.types.LibrarySet; +import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum; + +/** + * Abstract adapter for ld-like linkers + * + * @author Curt Arnold + */ +public abstract class AbstractLdLinker extends CommandLineLinker { + private String outputPrefix; + protected AbstractLdLinker(String command, String identifierArg, + String[] extensions, String[] ignoredExtensions, + String outputPrefix, String outputSuffix, boolean isLibtool, + AbstractLdLinker libtoolLinker) { + super(command, identifierArg, extensions, ignoredExtensions, + outputSuffix, isLibtool, libtoolLinker); + this.outputPrefix = outputPrefix; + } + public void addBase(long base, Vector args) { + if (base >= 0) { + args.addElement("--image-base"); + args.addElement(Long.toHexString(base)); + } + } + public void addFixed(Boolean fixed, Vector args) { + } + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args) { + if (debug) { + args.addElement("-g"); + } + if (isDarwin()) { + if (linkType.isPluginModule()) { + args.addElement("-bundle"); + } else { + if (linkType.isSharedLibrary()) { + args.addElement("-prebind"); + args.addElement("-dynamiclib"); + } + } + } else { + if (linkType.isStaticRuntime()) { + args.addElement("-static"); + } + if (linkType.isPluginModule()) { + args.addElement("-shared"); + } else { + if (linkType.isSharedLibrary()) { + args.addElement("-shared"); + } + } + } + } + public void addIncremental(boolean incremental, Vector args) { + if (incremental) { + args.addElement("-i"); + } + } + protected int addLibraryPatterns(String[] libnames, StringBuffer buf, + String prefix, String extension, String[] patterns, int offset) { + for (int i = 0; i < libnames.length; i++) { + buf.setLength(0); + buf.append(prefix); + buf.append(libnames[i]); + buf.append(extension); + patterns[offset + i] = buf.toString(); + } + return offset + libnames.length; + } + public String[] addLibrarySets(CCTask task, LibrarySet[] libsets, + Vector preargs, Vector midargs, Vector endargs) { + Vector libnames = new Vector(); + super.addLibrarySets(task, libsets, preargs, midargs, endargs); + LibraryTypeEnum previousLibraryType = null; + for (int i = 0; i < libsets.length; i++) { + LibrarySet set = libsets[i]; + File libdir = set.getDir(null); + String[] libs = set.getLibs(); + if (libdir != null) { + if (set.getType() != null && + "framework".equals(set.getType().getValue()) && + isDarwin()) { + endargs.addElement("-F" + libdir.getAbsolutePath()); + } else { + endargs.addElement("-L" + libdir.getAbsolutePath()); + } + } + // + // if there has been a change of library type + // + if (set.getType() != previousLibraryType) { + if (set.getType() != null && "static".equals(set.getType().getValue())) { + endargs.addElement(getStaticLibFlag()); + previousLibraryType = set.getType(); + } else { + if (set.getType() == null || + !"framework".equals(set.getType().getValue()) || + !isDarwin()) { + endargs.addElement(getDynamicLibFlag()); + previousLibraryType = set.getType(); + } + } + } + StringBuffer buf = new StringBuffer("-l"); + if (set.getType() != null && + "framework".equals(set.getType().getValue()) && + isDarwin()) { + buf.setLength(0); + buf.append("-framework "); + } + int initialLength = buf.length(); + for (int j = 0; j < libs.length; j++) { + // + // reset the buffer to just "-l" + // + buf.setLength(initialLength); + // + // add the library name + buf.append(libs[j]); + libnames.addElement(libs[j]); + // + // add the argument to the list + endargs.addElement(buf.toString()); + } + } + String rc[] = new String[libnames.size()]; + for (int i = 0; i < libnames.size(); i++) { + rc[i] = (String) libnames.elementAt(i); + } + return rc; + } + public void addMap(boolean map, Vector args) { + if (map) { + args.addElement("-M"); + } + } + public void addStack(int stack, Vector args) { + if (stack > 0) { + args.addElement("--stack"); + args.addElement(Integer.toString(stack)); + } + } + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addEntry(int, java.util.Vector) + */ + protected void addEntry(String entry, Vector args) { + if (entry != null) { + args.addElement("-e"); + args.addElement(entry); + } + } + + public String getCommandFileSwitch(String commandFile) { + throw new IllegalStateException("ld does not support command files"); + } + /** + * Returns library path. + * + */ + protected File[] getEnvironmentIncludePath() { + return CUtil.getPathFromEnvironment("LIB", ":"); + } + public String getLibraryKey(File libfile) { + String libname = libfile.getName(); + int lastDot = libname.lastIndexOf('.'); + if (lastDot >= 0) { + return libname.substring(0, lastDot); + } + return libname; + } + /** + * Returns library path. + * + */ + public File[] getLibraryPath() { + return new File[0]; + } + public String[] getLibraryPatterns(String[] libnames, LibraryTypeEnum libType) { + StringBuffer buf = new StringBuffer(); + int patternCount = libnames.length; + if (libType == null) { + patternCount *= 2; + } + String[] patterns = new String[patternCount]; + int offset = 0; + if (libType == null || "static".equals(libType.getValue())) { + offset = addLibraryPatterns(libnames, buf, "lib", ".a", patterns, 0); + } + if (libType != null && "framework".equals(libType.getValue()) && isDarwin()) { + for(int i = 0; i < libnames.length; i++) { + buf.setLength(0); + buf.append(libnames[i]); + buf.append(".framework/"); + buf.append(libnames[i]); + patterns[offset++] = buf.toString(); + } + } else { + if (libType == null || !"static".equals(libType.getValue())) { + if (isHPUX()) { + offset = addLibraryPatterns(libnames, buf, "lib", ".sl", patterns, + offset); + } else { + offset = addLibraryPatterns(libnames, buf, "lib", ".so", patterns, + offset); + } + } + } + return patterns; + } + public int getMaximumCommandLength() { + return Integer.MAX_VALUE; + } + public String[] getOutputFileNames(String baseName, VersionInfo versionInfo) { + String[] baseNames = super.getOutputFileNames(baseName, versionInfo); + if (outputPrefix.length() > 0) { + for(int i = 0; i < baseNames.length; i++) { + baseNames[i] = outputPrefix + baseNames[i]; + } + } + return baseNames; + } + public String[] getOutputFileSwitch(String outputFile) { + return GccProcessor.getOutputFileSwitch("-o", outputFile); + } + + public boolean isCaseSensitive() { + return true; + } + protected boolean isHPUX() { + String osname = System.getProperty("os.name").toLowerCase(); + if (osname.indexOf("hp") >= 0 && osname.indexOf("ux") >= 0) { + return true; + } + return false; + } + /** + * 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 + */ + public String[] prepareArguments(CCTask task, String outputDir, + String outputFile, String[] sourceFiles, + CommandLineLinkerConfiguration config) { + // + // need to suppress sources that correspond to + // library set entries since they are already + // in the argument list + String[] libnames = config.getLibraryNames(); + if (libnames == null || libnames.length == 0) { + return super.prepareArguments(task, outputDir, outputFile, + sourceFiles, config); + } + // + // + // null out any sources that correspond to library names + // + String[] localSources = (String[]) sourceFiles.clone(); + int extra = 0; + for (int i = 0; i < libnames.length; i++) { + String libname = libnames[i]; + for (int j = 0; j < localSources.length; j++) { + if (localSources[j] != null + && localSources[j].indexOf(libname) > 0 + && localSources[j].indexOf("lib") > 0) { + String filename = new File(localSources[j]).getName(); + if (filename.startsWith("lib") + && filename.substring(3).startsWith(libname)) { + String extension = filename + .substring(libname.length() + 3); + if (extension.equals(".a") || extension.equals(".so") + || extension.equals(".sl")) { + localSources[j] = null; + extra++; + } + } + } + } + } + if (extra == 0) { + return super.prepareArguments(task, outputDir, outputFile, + sourceFiles, config); + } + String[] finalSources = new String[localSources.length - extra]; + int index = 0; + for (int i = 0; i < localSources.length; i++) { + if (localSources[i] != null) { + finalSources[index++] = localSources[i]; + } + } + return super.prepareArguments(task, outputDir, outputFile, + finalSources, config); + } + + protected String getDynamicLibFlag() { + return "-Bdynamic"; + } + + protected String getStaticLibFlag() { + return "-Bstatic"; + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccCCompiler.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccCCompiler.java new file mode 100644 index 0000000..999ccf7 --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccCCompiler.java @@ -0,0 +1,242 @@ +/* + * + * 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.gcc; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.compiler.Processor; +import net.sf.antcontrib.cpptasks.parser.CParser; +import net.sf.antcontrib.cpptasks.parser.FortranParser; +import net.sf.antcontrib.cpptasks.parser.Parser; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.types.Environment; +import net.sf.antcontrib.cpptasks.OptimizationEnum; + +/** + * Adapter for the GCC C/C++ compiler + * + * @author Adam Murdoch + */ +public final class GccCCompiler extends GccCompatibleCCompiler { + private final static String[] sourceExtensions = new String[]{".c", /* C */ + ".cc", /* C++ */ + ".cpp", /* C++ */ + ".cxx", /* C++ */ + ".c++", /* C++ */ + ".i", /* preprocessed C */ + ".ii", /* preprocessed C++ */ + ".f", /* FORTRAN */ + ".for", /* FORTRAN */ + ".m", /* Objective-C */ + ".mm", /* Objected-C++ */ + ".s" /* Assembly */ + }; + private final static String[] headerExtensions = new String[]{".h", ".hpp", + ".inl"}; + private static final GccCCompiler cppInstance = new GccCCompiler("c++", + sourceExtensions, headerExtensions, false, + new GccCCompiler("c++", sourceExtensions, headerExtensions, true, + null, false, null), false, null); + private static final GccCCompiler g77Instance = new GccCCompiler("g77", + sourceExtensions, headerExtensions, false, + new GccCCompiler("g77", sourceExtensions, headerExtensions, true, + null, false, null), false, null); + private static final GccCCompiler gppInstance = new GccCCompiler("g++", + sourceExtensions, headerExtensions, false, + new GccCCompiler("g++", sourceExtensions, headerExtensions, true, + null, false, null), false, null); + private static final GccCCompiler instance = new GccCCompiler("gcc", + sourceExtensions, headerExtensions, false, + new GccCCompiler("gcc", sourceExtensions, headerExtensions, true, + null, false, null), false, null); + /** + * Gets c++ adapter + */ + public static GccCCompiler getCppInstance() { + return cppInstance; + } + /** + * Gets g77 adapter + */ + public static GccCCompiler getG77Instance() { + return g77Instance; + } + /** + * Gets gpp adapter + */ + public static GccCCompiler getGppInstance() { + return gppInstance; + } + /** + * Gets gcc adapter + */ + public static GccCCompiler getInstance() { + return instance; + } + private String identifier; + private File[] includePath; + private boolean isPICMeaningful = true; + /** + * Private constructor. Use GccCCompiler.getInstance() to get singleton + * instance of this class. + */ + private GccCCompiler(String command, String[] sourceExtensions, + String[] headerExtensions, boolean isLibtool, + GccCCompiler libtoolCompiler, boolean newEnvironment, + Environment env) { + super(command, null, sourceExtensions, headerExtensions, isLibtool, + libtoolCompiler, newEnvironment, env); + isPICMeaningful = System.getProperty("os.name").indexOf("Windows") < 0; + } + public void addImpliedArgs(final Vector args, + final boolean debug, + final boolean multithreaded, + final boolean exceptions, + final LinkType linkType, + final Boolean rtti, + final OptimizationEnum optimization) { + super.addImpliedArgs(args, debug, multithreaded, + exceptions, linkType, rtti, optimization); + if (isPICMeaningful && linkType.isSharedLibrary()) { + args.addElement("-fPIC"); + } + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + if (newEnvironment || env != null) { + return new GccCCompiler(getCommand(), this.getSourceExtensions(), + this.getHeaderExtensions(), this.getLibtool(), + (GccCCompiler) this.getLibtoolCompiler(), newEnvironment, + env); + } + return this; + } + /** + * Create parser to determine dependencies. + * + * Will create appropriate parser (C++, FORTRAN) based on file extension. + * + */ + protected Parser createParser(File source) { + if (source != null) { + String sourceName = source.getName(); + int lastDot = sourceName.lastIndexOf('.'); + if (lastDot >= 0 && lastDot + 1 < sourceName.length()) { + char afterDot = sourceName.charAt(lastDot + 1); + if (afterDot == 'f' || afterDot == 'F') { + return new FortranParser(); + } + } + } + return new CParser(); + } + public File[] getEnvironmentIncludePath() { + if (includePath == null) { + // + // construct default include path from machine id and version id + // + String[] defaultInclude = new String[1]; + StringBuffer buf = new StringBuffer("/lib/"); + buf.append(GccProcessor.getMachine()); + buf.append('/'); + buf.append(GccProcessor.getVersion()); + buf.append("/include"); + defaultInclude[0] = buf.toString(); + // + // read specs file and look for -istart and -idirafter + // + String[] specs = GccProcessor.getSpecs(); + String[][] optionValues = GccProcessor.parseSpecs(specs, "*cpp:", + new String[]{"-isystem ", "-idirafter "}); + // + // if no entries were found, then use a default path + // + if (optionValues[0].length == 0 && optionValues[1].length == 0) { + optionValues[0] = new String[]{"/usr/local/include", + "/usr/include", "/usr/include/win32api"}; + } + // + // remove mingw entries. + // For MinGW compiles this will mean the + // location of the sys includes will be + // wrong in dependencies.xml + // but that should have no significant effect + for (int i = 0; i < optionValues.length; i++) { + for (int j = 0; j < optionValues[i].length; j++) { + if (optionValues[i][j].indexOf("mingw") > 0) { + optionValues[i][j] = null; + } + } + } + // + // if cygwin then + // we have to prepend location of gcc32 + // and .. to start of absolute filenames to + // have something that will exist in the + // windows filesystem + if (GccProcessor.isCygwin()) { + GccProcessor.convertCygwinFilenames(optionValues[0]); + GccProcessor.convertCygwinFilenames(optionValues[1]); + GccProcessor.convertCygwinFilenames(defaultInclude); + } + int count = CUtil.checkDirectoryArray(optionValues[0]); + count += CUtil.checkDirectoryArray(optionValues[1]); + count += CUtil.checkDirectoryArray(defaultInclude); + includePath = new File[count]; + int index = 0; + for (int i = 0; i < optionValues.length; i++) { + for (int j = 0; j < optionValues[i].length; j++) { + if (optionValues[i][j] != null) { + includePath[index++] = new File(optionValues[i][j]); + } + } + } + for (int i = 0; i < defaultInclude.length; i++) { + if (defaultInclude[i] != null) { + includePath[index++] = new File(defaultInclude[i]); + } + } + } + return (File[]) includePath.clone(); + } + public String getIdentifier() throws BuildException { + if (identifier == null) { + StringBuffer buf; + if (getLibtool()) { + buf = new StringBuffer("libtool "); + } else { + buf = new StringBuffer(' '); + } + buf.append(getCommand()); + buf.append(' '); + buf.append(GccProcessor.getVersion()); + buf.append(' '); + buf.append(GccProcessor.getMachine()); + identifier = buf.toString(); + } + return identifier; + } + public Linker getLinker(LinkType linkType) { + return GccLinker.getInstance().getLinker(linkType); + } + public int getMaximumCommandLength() { + return Integer.MAX_VALUE; + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccCompatibleCCompiler.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccCompatibleCCompiler.java new file mode 100644 index 0000000..0485fba --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccCompatibleCCompiler.java @@ -0,0 +1,146 @@ +/* + * + * 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.gcc; +import java.io.File; +import java.util.Vector; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CommandLineCCompiler; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import org.apache.tools.ant.types.Environment; +import net.sf.antcontrib.cpptasks.OptimizationEnum; + +/** + * Abstract base class for compilers that attempt to be command line compatible + * with GCC + * + * @author Adam Murdoch + * @author Curt Arnold + */ +public abstract class GccCompatibleCCompiler extends CommandLineCCompiler { + private final static String[] headerExtensions = new String[]{".h", ".hpp", + ".inl"}; + private final static String[] sourceExtensions = new String[]{".c", ".cc", + ".cpp", ".cxx", ".c++", ".i", ".f", ".for"}; + /** + * Private constructor. Use GccCCompiler.getInstance() to get singleton + * instance of this class. + */ + protected GccCompatibleCCompiler(String command, String identifierArg, + boolean libtool, GccCompatibleCCompiler libtoolCompiler, + boolean newEnvironment, Environment env) { + super(command, identifierArg, sourceExtensions, headerExtensions, + libtool ? ".fo" : ".o", libtool, libtoolCompiler, + newEnvironment, env); + } + /** + * Private constructor. Use GccCCompiler.getInstance() to get singleton + * instance of this class. + */ + protected GccCompatibleCCompiler(String command, String identifierArg, + String[] sourceExtensions, String[] headerExtensions, + boolean libtool, GccCompatibleCCompiler libtoolCompiler, + boolean newEnvironment, Environment env) { + super(command, identifierArg, sourceExtensions, headerExtensions, + libtool ? ".fo" : ".o", libtool, libtoolCompiler, + newEnvironment, env); + } + public void addImpliedArgs(final Vector args, + final boolean debug, + final boolean multithreaded, + final boolean exceptions, + final LinkType linkType, + final Boolean rtti, + final OptimizationEnum optimization) { + // + // -fPIC is too much trouble + // users have to manually add it for + // operating systems that make sense + // + args.addElement("-c"); + if (debug) { + args.addElement("-g"); + } else { + if (optimization != null) { + if (optimization.isSize()) { + args.addElement("-Os"); + } else if (optimization.isSpeed()) { + if ("full".equals(optimization.getValue())) { + args.addElement("-O2"); + } else { + if ("speed".equals(optimization.getValue())) { + args.addElement("-O1"); + } else { + args.addElement("-O3"); + } + } + } + } + } + if (getIdentifier().indexOf("mingw") >= 0) { + if (linkType.isSubsystemConsole()) { + args.addElement("-mconsole"); + } + if (linkType.isSubsystemGUI()) { + args.addElement("-mwindows"); + } + } + if (rtti != null && !rtti.booleanValue()) { + args.addElement("-fno-rtti"); + } + + } + /** + * Adds an include path to the command. + */ + public void addIncludePath(String path, Vector cmd) { + cmd.addElement("-I" + path); + } + public void addWarningSwitch(Vector args, int level) { + switch (level) { + case 0 : + args.addElement("-w"); + break; + case 5 : + args.addElement("-Werror"); + /* nobreak */ + case 4 : + args.addElement("-W"); + /* nobreak */ + case 3 : + args.addElement("-Wall"); + break; + } + } + public void getDefineSwitch(StringBuffer buffer, String define, String value) { + buffer.append("-D"); + buffer.append(define); + if (value != null && value.length() > 0) { + buffer.append('='); + buffer.append(value); + } + } + protected File[] getEnvironmentIncludePath() { + return CUtil.getPathFromEnvironment("INCLUDE", ":"); + } + public String getIncludeDirSwitch(String includeDir) { + return "-I" + includeDir; + } + public void getUndefineSwitch(StringBuffer buffer, String define) { + buffer.append("-U"); + buffer.append(define); + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccLibrarian.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccLibrarian.java new file mode 100644 index 0000000..0c6ae4b --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccLibrarian.java @@ -0,0 +1,41 @@ +/* + * + * 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.gcc; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +/** + * Adapter for the 'ar' archiver + * + * @author Adam Murdoch + */ +public final class GccLibrarian extends AbstractArLibrarian { + private static String[] objFileExtensions = new String[]{".o"}; + private static GccLibrarian instance = new GccLibrarian("ar", + objFileExtensions, false, new GccLibrarian("ar", objFileExtensions, + true, null)); + public static GccLibrarian getInstance() { + return instance; + } + private GccLibrarian(String command, String[] inputExtensions, + boolean isLibtool, GccLibrarian libtoolLibrarian) { + super(command, "V", inputExtensions, new String[0], "lib", ".a", + isLibtool, libtoolLibrarian); + } + public Linker getLinker(LinkType type) { + return GccLinker.getInstance().getLinker(type); + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccLinker.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccLinker.java new file mode 100644 index 0000000..c4720c8 --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccLinker.java @@ -0,0 +1,210 @@ +/* + * + * 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.gcc; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +/** + * Adapter for the GCC linker + * + * @author Adam Murdoch + */ +public class GccLinker extends AbstractLdLinker { + private static final String[] discardFiles = new String[0]; + private static final String[] objFiles = new String[]{".o", ".a", ".lib", + ".dll", ".so", ".sl"}; + private static final String[] libtoolObjFiles = new String[]{".fo", ".a", + ".lib", ".dll", ".so", ".sl"}; + private static String[] linkerOptions = new String[]{"-bundle", + "-dynamiclib", "-nostartfiles", "-nostdlib", "-prebind", "-s", + "-static", "-shared", "-symbolic", "-Xlinker", + "--export-all-symbols", "-static-libgcc",}; + private static final GccLinker dllLinker = new GccLinker("gcc", objFiles, + discardFiles, "lib", ".so", false, new GccLinker("gcc", objFiles, + discardFiles, "lib", ".so", true, null)); + private static final GccLinker instance = new GccLinker("gcc", objFiles, + discardFiles, "", "", false, null); + private static final GccLinker machBundleLinker = new GccLinker("gcc", + objFiles, discardFiles, "lib", ".bundle", false, null); + private static final GccLinker machDllLinker = new GccLinker("gcc", + objFiles, discardFiles, "lib", ".dylib", false, null); + public static GccLinker getInstance() { + return instance; + } + private File[] libDirs; + protected GccLinker(String command, String[] extensions, + String[] ignoredExtensions, String outputPrefix, + String outputSuffix, boolean isLibtool, GccLinker libtoolLinker) { + super(command, "-dumpversion", extensions, ignoredExtensions, + outputPrefix, outputSuffix, isLibtool, libtoolLinker); + } + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args) { + super.addImpliedArgs(debug, linkType, args); + if (getIdentifier().indexOf("mingw") >= 0) { + if (linkType.isSubsystemConsole()) { + args.addElement("-mconsole"); + } + if (linkType.isSubsystemGUI()) { + args.addElement("-mwindows"); + } + } + } + /** + * 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 + */ + public String decorateLinkerOption(StringBuffer buf, String arg) { + String decoratedArg = arg; + if (arg.length() > 1 && arg.charAt(0) == '-') { + switch (arg.charAt(1)) { + // + // passed automatically by GCC + // + case 'g' : + case 'f' : + case 'F' : + /* Darwin */ + case 'm' : + case 'O' : + case 'W' : + case 'l' : + case 'L' : + case 'u' : + case 'v' : + break; + default : + boolean known = false; + for (int i = 0; i < linkerOptions.length; i++) { + if (linkerOptions[i].equals(arg)) { + known = true; + break; + } + } + if (!known) { + buf.setLength(0); + buf.append("-Wl,"); + buf.append(arg); + decoratedArg = buf.toString(); + } + break; + } + } + return decoratedArg; + } + /** + * Returns library path. + * + */ + public File[] getLibraryPath() { + if (libDirs == null) { + // + // construct gcc lib path from machine and version + // + StringBuffer buf = new StringBuffer("/lib/gcc-lib/"); + buf.append(GccProcessor.getMachine()); + buf.append('/'); + buf.append(GccProcessor.getVersion()); + // + // build default path from gcc and system /lib and /lib/w32api + // + String[] impliedLibPath = new String[]{buf.toString(), + "/lib/w32api", "/lib"}; + // + // read gcc specs file for other library paths + // + String[] specs = GccProcessor.getSpecs(); + String[][] libpaths = GccProcessor.parseSpecs(specs, "*link:", + new String[]{"%q"}); + String[] libpath; + if (libpaths[0].length > 0) { + libpath = new String[libpaths[0].length + 3]; + int i = 0; + for (; i < libpaths[0].length; i++) { + libpath[i] = libpaths[0][i]; + } + libpath[i++] = buf.toString(); + libpath[i++] = "/lib/w32api"; + libpath[i++] = "/lib"; + } else { + // + // if a failure to find any matches then + // use some default values for lib path entries + libpath = new String[]{"/usr/local/lib/mingw", + "/usr/local/lib", "/usr/lib/w32api", "/usr/lib/mingw", + "/usr/lib", buf.toString(), "/lib/w32api", "/lib"}; + } + for (int i = 0; i < libpath.length; i++) { + if (libpath[i].indexOf("mingw") >= 0) { + libpath[i] = null; + } + } + // + // if cygwin then + // we have to prepend location of gcc32 + // and .. to start of absolute filenames to + // have something that will exist in the + // windows filesystem + if (GccProcessor.isCygwin()) { + GccProcessor.convertCygwinFilenames(libpath); + } + // + // check that remaining entries are actual directories + // + int count = CUtil.checkDirectoryArray(libpath); + // + // populate return array with remaining entries + // + libDirs = new File[count]; + int index = 0; + for (int i = 0; i < libpath.length; i++) { + if (libpath[i] != null) { + libDirs[index++] = new File(libpath[i]); + } + } + } + return libDirs; + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return GccLibrarian.getInstance(); + } + if (type.isPluginModule()) { + if (isDarwin()) { + return machBundleLinker; + } else { + return dllLinker; + } + } + if (type.isSharedLibrary()) { + if (isDarwin()) { + return machDllLinker; + } else { + return dllLinker; + } + } + return instance; + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccProcessor.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccProcessor.java new file mode 100644 index 0000000..058ef12 --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccProcessor.java @@ -0,0 +1,299 @@ +/* + * + * 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.gcc; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CaptureStreamHandler; +/** + * A add-in class for Gcc processors + * + * + */ +public class GccProcessor { + // the results from gcc -dumpmachine + private static String machine; + private static String[] specs; + // the results from gcc -dumpversion + private static String version; + private static int addLibraryPatterns(String[] libnames, StringBuffer buf, + String prefix, String extension, String[] patterns, int offset) { + for (int i = 0; i < libnames.length; i++) { + buf.setLength(0); + buf.append(prefix); + buf.append(libnames[i]); + buf.append(extension); + patterns[offset + i] = buf.toString(); + } + return offset + libnames.length; + } + /** + * Converts absolute Cygwin file or directory names to the corresponding + * Win32 name. + * + * @param names + * array of names, some elements may be null, will be changed in + * place. + */ + public static void convertCygwinFilenames(String[] names) { + if (names == null) { + throw new NullPointerException("names"); + } + File gccDir = CUtil.getExecutableLocation("gcc.exe"); + if (gccDir != null) { + String prefix = gccDir.getAbsolutePath() + "/.."; + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < names.length; i++) { + String name = names[i]; + if (name != null && name.length() > 1 && name.charAt(0) == '/') { + buf.setLength(0); + buf.append(prefix); + buf.append(name); + names[i] = buf.toString(); + } + } + } + } + public static String[] getLibraryPatterns(String[] libnames) { + StringBuffer buf = new StringBuffer(); + String[] patterns = new String[libnames.length * 2]; + int offset = addLibraryPatterns(libnames, buf, "lib", ".a", patterns, 0); + if (isHPUX()) { + offset = addLibraryPatterns(libnames, buf, "lib", ".sl", patterns, + offset); + } else { + offset = addLibraryPatterns(libnames, buf, "lib", ".so", patterns, + offset); + } + return patterns; + } + public static String getMachine() { + if (machine == null) { + String[] args = new String[]{"gcc", "-dumpmachine"}; + String[] cmdout = CaptureStreamHandler.run(args); + if (cmdout.length == 0) { + machine = "nomachine"; + } else { + machine = cmdout[0]; + } + } + return machine; + } + public static String[] getOutputFileSwitch(String letter, String outputFile) { + StringBuffer buf = new StringBuffer(); + if (outputFile.indexOf(' ') >= 0) { + buf.append('"'); + buf.append(outputFile.replace('\\', '/')); + buf.append('"'); + } else { + buf.append(outputFile.replace('\\', '/')); + } + String[] retval = new String[]{letter, buf.toString()}; + return retval; + } + /** + * Returns the contents of the gcc specs file. + * + * The implementation locates gcc.exe in the executable path and then + * builds a relative path name from the results of -dumpmachine and + * -dumpversion. Attempts to use gcc -dumpspecs to provide this information + * resulted in stalling on the Execute.run + * + * @returns contents of the specs file + */ + public static String[] getSpecs() { + if (specs == null) { + File gccParent = CUtil.getExecutableLocation("gcc.exe"); + if (gccParent != null) { + // + // build a relative path like + // ../lib/gcc-lib/i686-pc-cygwin/2.95.3-5/specs + // + StringBuffer buf = new StringBuffer("../lib/gcc-lib/"); + buf.append(getMachine()); + buf.append('/'); + buf.append(getVersion()); + buf.append("/specs"); + // + // resolve it relative to the location of gcc.exe + // + String relativePath = buf.toString(); + File specsFile = new File(gccParent, relativePath); + // + // found the specs file + // + try { + // + // read the lines in the file + // + BufferedReader reader = new BufferedReader(new FileReader( + specsFile)); + Vector lines = new Vector(100); + String line = reader.readLine(); + while (line != null) { + lines.addElement(line); + line = reader.readLine(); + } + specs = new String[lines.size()]; + lines.copyInto(specs); + } catch (IOException ex) { + } + } + } + if (specs == null) { + specs = new String[0]; + } + return specs; + } + public static String getVersion() { + if (version == null) { + String[] args = new String[]{"gcc", "-dumpversion"}; + String[] cmdout = CaptureStreamHandler.run(args); + if (cmdout.length == 0) { + version = "noversion"; + } else { + version = cmdout[0]; + } + } + return version; + } + public static boolean isCaseSensitive() { + return true; + } + /** + * Determines if task is running with cygwin + * + * @return true if cygwin was detected + */ + public static boolean isCygwin() { + return getMachine().indexOf("cygwin") > 0; + } + private static boolean isHPUX() { + String osname = System.getProperty("os.name").toLowerCase(); + if (osname.indexOf("hp") >= 0 && osname.indexOf("ux") >= 0) { + return true; + } + return false; + } + /** + * + * Parses the results of the specs file for a specific processor and + * options + * + * @param specsContent + * Contents of specs file as returned from getSpecs + * @param specSectionStart + * start of spec section, for example "*cpp:" + * @param options + * command line switches such as "-istart" + */ + public static String[][] parseSpecs(String[] specsContent, + String specSectionStart, String[] options) { + if (specsContent == null) { + throw new NullPointerException("specsContent"); + } + if (specSectionStart == null) { + throw new NullPointerException("specSectionStart"); + } + if (options == null) { + throw new NullPointerException("option"); + } + String[][] optionValues = new String[options.length][]; + StringBuffer optionValue = new StringBuffer(40); + for (int i = 0; i < specsContent.length; i++) { + String specLine = specsContent[i]; + // + // if start of section then start paying attention + // + if (specLine.startsWith(specSectionStart)) { + Vector[] optionVectors = new Vector[options.length]; + for (int j = 0; j < options.length; j++) { + optionVectors[j] = new Vector(10); + } + // + // go to next line and examine contents + // and repeat until end of file + // + for (i++; i < specsContent.length; i++) { + specLine = specsContent[i]; + for (int j = 0; j < options.length; j++) { + int optionStart = specLine.indexOf(options[j]); + while (optionStart >= 0) { + optionValue.setLength(0); + // + // walk rest of line looking for first non + // whitespace + // and then next space + boolean hasNonBlank = false; + int k = optionStart + options[j].length(); + for (; k < specLine.length(); k++) { + // + // either a blank or a "}" (close of + // conditional) + // section will end the path + // + if (specLine.charAt(k) == ' ' + || specLine.charAt(k) == '}') { + if (hasNonBlank) { + break; + } + } else { + hasNonBlank = true; + optionValue.append(specLine.charAt(k)); + } + } + // + // transition back to whitespace + // value is over, add it to vector + if (hasNonBlank) { + optionVectors[j].addElement(optionValue + .toString()); + } + // + // find next occurance on line + // + optionStart = specLine.indexOf(options[j], k); + } + } + } + // + // copy vectors over to option arrays + // + for (int j = 0; j < options.length; j++) { + optionValues[j] = new String[optionVectors[j].size()]; + optionVectors[j].copyInto(optionValues[j]); + } + } + } + // + // fill in any missing option values with + // a zero-length string array + for (int i = 0; i < optionValues.length; i++) { + String[] zeroLenArray = new String[0]; + if (optionValues[i] == null) { + optionValues[i] = zeroLenArray; + } + } + return optionValues; + } + private GccProcessor() { + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/GppLinker.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/GppLinker.java new file mode 100644 index 0000000..f3bc174 --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/GppLinker.java @@ -0,0 +1,203 @@ +/* + * + * Copyright 2003-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.gcc; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CaptureStreamHandler; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.types.LibrarySet; +/** + * Adapter for the g++ variant of the GCC linker + * + * @author Stephen M. Webb <[email protected]> + */ +public class GppLinker extends AbstractLdLinker { + protected static final String[] discardFiles = new String[0]; + protected static final String[] objFiles = new String[]{".o", ".a", ".lib", + ".dll", ".so", ".sl"}; + private static final GppLinker dllLinker = new GppLinker("gcc", objFiles, + discardFiles, "lib", ".so", false, new GppLinker("gcc", objFiles, + discardFiles, "lib", ".so", true, null)); + private final static String libPrefix = "libraries: ="; + protected static final String[] libtoolObjFiles = new String[]{".fo", ".a", + ".lib", ".dll", ".so", ".sl"}; + private static String[] linkerOptions = new String[]{"-bundle", "-dylib", + "-dynamic", "-dynamiclib", "-nostartfiles", "-nostdlib", + "-prebind", "-s", "-static", "-shared", "-symbolic", "-Xlinker"}; + private static final GppLinker instance = new GppLinker("gcc", objFiles, + discardFiles, "", "", false, null); + private static final GppLinker machDllLinker = new GppLinker("gcc", + objFiles, discardFiles, "lib", ".dylib", false, null); + private static final GppLinker machPluginLinker = new GppLinker("gcc", + objFiles, discardFiles, "lib", ".bundle", false, null); + public static GppLinker getInstance() { + return instance; + } + private File[] libDirs; + private String runtimeLibrary; + protected GppLinker(String command, String[] extensions, + String[] ignoredExtensions, String outputPrefix, + String outputSuffix, boolean isLibtool, GppLinker libtoolLinker) { + super(command, "-dumpversion", extensions, ignoredExtensions, + outputPrefix, outputSuffix, isLibtool, libtoolLinker); + } + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args) { + super.addImpliedArgs(debug, linkType, args); + if (getIdentifier().indexOf("mingw") >= 0) { + if (linkType.isSubsystemConsole()) { + args.addElement("-mconsole"); + } + if (linkType.isSubsystemGUI()) { + args.addElement("-mwindows"); + } + } + if (linkType.isStaticRuntime()) { + String[] cmdin = new String[]{"g++", "-print-file-name=libstdc++.a"}; + String[] cmdout = CaptureStreamHandler.run(cmdin); + if (cmdout.length > 0) { + runtimeLibrary = cmdout[0]; + } else { + runtimeLibrary = null; + } + } else { + runtimeLibrary = "-lstdc++"; + } + } + public String[] addLibrarySets(CCTask task, LibrarySet[] libsets, + Vector preargs, Vector midargs, Vector endargs) { + String[] rs = super.addLibrarySets(task, libsets, preargs, midargs, + endargs); + if (runtimeLibrary != null) { + endargs.addElement(runtimeLibrary); + } + return rs; + } + /** + * Allows drived linker to decorate linker option. Override by GppLinker 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 + */ + public String decorateLinkerOption(StringBuffer buf, String arg) { + String decoratedArg = arg; + if (arg.length() > 1 && arg.charAt(0) == '-') { + switch (arg.charAt(1)) { + // + // passed automatically by GCC + // + case 'g' : + case 'f' : + case 'F' : + /* Darwin */ + case 'm' : + case 'O' : + case 'W' : + case 'l' : + case 'L' : + case 'u' : + break; + default : + boolean known = false; + for (int i = 0; i < linkerOptions.length; i++) { + if (linkerOptions[i].equals(arg)) { + known = true; + break; + } + } + if (!known) { + buf.setLength(0); + buf.append("-Wl,"); + buf.append(arg); + decoratedArg = buf.toString(); + } + break; + } + } + return decoratedArg; + } + /** + * Returns library path. + * + */ + public File[] getLibraryPath() { + if (libDirs == null) { + Vector dirs = new Vector(); + // Ask GCC where it will look for its libraries. + String[] args = new String[]{"g++", "-print-search-dirs"}; + String[] cmdout = CaptureStreamHandler.run(args); + for (int i = 0; i < cmdout.length; ++i) { + int prefixIndex = cmdout[i].indexOf(libPrefix); + if (prefixIndex >= 0) { + // Special case DOS-type GCCs like MinGW or Cygwin + int s = prefixIndex + libPrefix.length(); + int t = cmdout[i].indexOf(';', s); + while (t > 0) { + dirs.addElement(cmdout[i].substring(s, t)); + s = t + 1; + t = cmdout[i].indexOf(';', s); + } + dirs.addElement(cmdout[i].substring(s)); + ++i; + for (; i < cmdout.length; ++i) { + dirs.addElement(cmdout[i]); + } + } + } + // Eliminate all but actual directories. + String[] libpath = new String[dirs.size()]; + dirs.copyInto(libpath); + int count = CUtil.checkDirectoryArray(libpath); + // Build return array. + libDirs = new File[count]; + int index = 0; + for (int i = 0; i < libpath.length; ++i) { + if (libpath[i] != null) { + libDirs[index++] = new File(libpath[i]); + } + } + } + return libDirs; + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return GccLibrarian.getInstance(); + } + if (type.isPluginModule()) { + if (GccProcessor.getMachine().indexOf("darwin") >= 0) { + return machPluginLinker; + } else { + return dllLinker; + } + } + if (type.isSharedLibrary()) { + if (GccProcessor.getMachine().indexOf("darwin") >= 0) { + return machDllLinker; + } else { + return dllLinker; + } + } + return instance; + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/LdLinker.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/LdLinker.java new file mode 100644 index 0000000..2104e34 --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/LdLinker.java @@ -0,0 +1,57 @@ +/* + * + * 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.gcc; +import java.io.File; + +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +/** + * Adapter for the 'ld' linker + * + * @author Curt Arnold + */ +public final class LdLinker extends AbstractLdLinker { + private static final String[] discardFiles = new String[0]; + private static final String[] objFiles = new String[]{".o", ".a", ".lib", + ".dll", ".so", ".sl"}; + private static final LdLinker dllLinker = new LdLinker("ld", objFiles, + discardFiles, "lib", ".so", false, new LdLinker("ld", objFiles, + discardFiles, "lib", ".so", true, null)); + private static final LdLinker instance = new LdLinker("ld", objFiles, + discardFiles, "", "", false, null); + private static final String[] libtoolObjFiles = new String[]{".fo", ".a", + ".lib", ".dll", ".so", ".sl"}; + public static LdLinker getInstance() { + return instance; + } + private File[] libDirs; + private LdLinker(String command, String[] extensions, + String[] ignoredExtensions, String outputPrefix, + String outputSuffix, boolean isLibtool, LdLinker libtoolLinker) { + super(command, "-version", extensions, ignoredExtensions, outputPrefix, + outputSuffix, isLibtool, libtoolLinker); + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return GccLibrarian.getInstance(); + } + if (type.isSharedLibrary()) { + return dllLinker; + } + return instance; + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/GccCCompiler.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/GccCCompiler.java new file mode 100755 index 0000000..86a8ac7 --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/GccCCompiler.java @@ -0,0 +1,272 @@ +/* + * + * 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.gcc.cross; +import java.io.File; +import java.util.Vector; +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.CompilerParam; +import net.sf.antcontrib.cpptasks.compiler.CommandLineCompilerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.compiler.Processor; +import net.sf.antcontrib.cpptasks.compiler.ProgressMonitor; +import net.sf.antcontrib.cpptasks.gcc.GccCompatibleCCompiler; +import net.sf.antcontrib.cpptasks.parser.CParser; +import net.sf.antcontrib.cpptasks.parser.FortranParser; +import net.sf.antcontrib.cpptasks.parser.Parser; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.types.Environment; +import net.sf.antcontrib.cpptasks.OptimizationEnum; + +/** + * Adapter for the GCC C/C++ compiler + * + * @author Adam Murdoch + */ +public final class GccCCompiler extends GccCompatibleCCompiler { + private final static String[] headerExtensions = new String[]{".h", ".hpp", + ".inl"}; + private final static String[] sourceExtensions = new String[]{".c", /* C */ + ".cc", /* C++ */ + ".cpp", /* C++ */ + ".cxx", /* C++ */ + ".c++", /* C++ */ + ".i", /* preprocessed C */ + ".ii", /* preprocessed C++ */ + ".f", /* FORTRAN */ + ".for", /* FORTRAN */ + ".m", /* Objective-C */ + ".mm", /* Objected-C++ */ + ".s" /* Assembly */ + }; + private static final GccCCompiler cppInstance = new GccCCompiler("c++", + sourceExtensions, headerExtensions, false, + new GccCCompiler("c++", sourceExtensions, headerExtensions, true, + null, false, null), false, null); + private static final GccCCompiler g77Instance = new GccCCompiler("g77", + sourceExtensions, headerExtensions, false, + new GccCCompiler("g77", sourceExtensions, headerExtensions, true, + null, false, null), false, null); + private static final GccCCompiler gppInstance = new GccCCompiler("g++", + sourceExtensions, headerExtensions, false, + new GccCCompiler("g++", sourceExtensions, headerExtensions, true, + null, false, null), false, null); + private static final GccCCompiler instance = new GccCCompiler("gcc", + sourceExtensions, headerExtensions, false, + new GccCCompiler("gcc", sourceExtensions, headerExtensions, true, + null, false, null), false, null); + /** + * Gets c++ adapter + */ + public static GccCCompiler getCppInstance() { + return cppInstance; + } + /** + * Gets g77 adapter + */ + public static GccCCompiler getG77Instance() { + return g77Instance; + } + /** + * Gets gpp adapter + */ + public static GccCCompiler getGppInstance() { + return gppInstance; + } + /** + * Gets gcc adapter + */ + public static GccCCompiler getInstance() { + return instance; + } + private String identifier; + private File[] includePath; + private boolean isPICMeaningful = true; + /** + * Private constructor. Use GccCCompiler.getInstance() to get singleton + * instance of this class. + */ + private GccCCompiler(String command, String[] sourceExtensions, + String[] headerExtensions, boolean isLibtool, + GccCCompiler libtoolCompiler, boolean newEnvironment, + Environment env) { + super(command, null, sourceExtensions, headerExtensions, isLibtool, + libtoolCompiler, newEnvironment, env); + isPICMeaningful = System.getProperty("os.name").indexOf("Windows") < 0; + } + public void addImpliedArgs(final Vector args, + final boolean debug, + final boolean multithreaded, + final boolean exceptions, + final LinkType linkType, + final Boolean rtti, + final OptimizationEnum optimization) { + super.addImpliedArgs(args, debug, multithreaded, + exceptions, linkType, rtti, optimization); + if (isPICMeaningful && linkType.isSharedLibrary()) { + args.addElement("-fPIC"); + } + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + if (newEnvironment || env != null) { + return new GccCCompiler(getCommand(), this.getSourceExtensions(), + this.getHeaderExtensions(), this.getLibtool(), + (GccCCompiler) this.getLibtoolCompiler(), newEnvironment, + env); + } + return this; + } + protected Object clone() throws CloneNotSupportedException { + GccCCompiler clone = (GccCCompiler) super.clone(); + return clone; + } + public void compile(CCTask task, File outputDir, String[] sourceFiles, + String[] args, String[] endArgs, boolean relentless, + CommandLineCompilerConfiguration config, ProgressMonitor monitor) + throws BuildException { + try { + GccCCompiler clone = (GccCCompiler) this.clone(); + CompilerParam param = config.getParam("target"); + if (param != null) + clone.setCommand(param.getValue() + "-" + this.getCommand()); + clone.supercompile(task, outputDir, sourceFiles, args, endArgs, + relentless, config, monitor); + } catch (CloneNotSupportedException e) { + supercompile(task, outputDir, sourceFiles, args, endArgs, + relentless, config, monitor); + } + } + /** + * Create parser to determine dependencies. + * + * Will create appropriate parser (C++, FORTRAN) based on file extension. + * + */ + protected Parser createParser(File source) { + if (source != null) { + String sourceName = source.getName(); + int lastDot = sourceName.lastIndexOf('.'); + if (lastDot >= 0 && lastDot + 1 < sourceName.length()) { + char afterDot = sourceName.charAt(lastDot + 1); + if (afterDot == 'f' || afterDot == 'F') { + return new FortranParser(); + } + } + } + return new CParser(); + } + public File[] getEnvironmentIncludePath() { + if (includePath == null) { + // + // construct default include path from machine id and version id + // + String[] defaultInclude = new String[1]; + StringBuffer buf = new StringBuffer("/lib/"); + buf.append(GccProcessor.getMachine()); + buf.append('/'); + buf.append(GccProcessor.getVersion()); + buf.append("/include"); + defaultInclude[0] = buf.toString(); + // + // read specs file and look for -istart and -idirafter + // + String[] specs = GccProcessor.getSpecs(); + String[][] optionValues = GccProcessor.parseSpecs(specs, "*cpp:", + new String[]{"-isystem ", "-idirafter "}); + // + // if no entries were found, then use a default path + // + if (optionValues[0].length == 0 && optionValues[1].length == 0) { + optionValues[0] = new String[]{"/usr/local/include", + "/usr/include", "/usr/include/win32api"}; + } + // + // remove mingw entries. + // For MinGW compiles this will mean the + // location of the sys includes will be + // wrong in dependencies.xml + // but that should have no significant effect + for (int i = 0; i < optionValues.length; i++) { + for (int j = 0; j < optionValues[i].length; j++) { + if (optionValues[i][j].indexOf("mingw") > 0) { + optionValues[i][j] = null; + } + } + } + // + // if cygwin then + // we have to prepend location of gcc32 + // and .. to start of absolute filenames to + // have something that will exist in the + // windows filesystem + if (GccProcessor.isCygwin()) { + GccProcessor.convertCygwinFilenames(optionValues[0]); + GccProcessor.convertCygwinFilenames(optionValues[1]); + GccProcessor.convertCygwinFilenames(defaultInclude); + } + int count = CUtil.checkDirectoryArray(optionValues[0]); + count += CUtil.checkDirectoryArray(optionValues[1]); + count += CUtil.checkDirectoryArray(defaultInclude); + includePath = new File[count]; + int index = 0; + for (int i = 0; i < optionValues.length; i++) { + for (int j = 0; j < optionValues[i].length; j++) { + if (optionValues[i][j] != null) { + includePath[index++] = new File(optionValues[i][j]); + } + } + } + for (int i = 0; i < defaultInclude.length; i++) { + if (defaultInclude[i] != null) { + includePath[index++] = new File(defaultInclude[i]); + } + } + } + return (File[]) includePath.clone(); + } + public String getIdentifier() throws BuildException { + if (identifier == null) { + StringBuffer buf; + if (getLibtool()) { + buf = new StringBuffer("libtool "); + } else { + buf = new StringBuffer(' '); + } + buf.append(getCommand()); + buf.append(' '); + buf.append(GccProcessor.getVersion()); + buf.append(' '); + buf.append(GccProcessor.getMachine()); + identifier = buf.toString(); + } + return identifier; + } + public Linker getLinker(LinkType linkType) { + return GccLinker.getInstance().getLinker(linkType); + } + public int getMaximumCommandLength() { + return Integer.MAX_VALUE; + } + private void supercompile(CCTask task, File outputDir, + String[] sourceFiles, String[] args, String[] endArgs, + boolean relentless, CommandLineCompilerConfiguration config, + ProgressMonitor monitor) throws BuildException { + super.compile(task, outputDir, sourceFiles, args, endArgs, relentless, + config, monitor); + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/GccLibrarian.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/GccLibrarian.java new file mode 100755 index 0000000..c9d28d9 --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/GccLibrarian.java @@ -0,0 +1,69 @@ +/* + * + * 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.gcc.cross; +import java.io.File; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.LinkerParam; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinkerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.gcc.AbstractArLibrarian; + +import org.apache.tools.ant.BuildException; +/** + * Adapter for the 'ar' archiver + * + * @author Adam Murdoch + */ +public final class GccLibrarian extends AbstractArLibrarian { + private static String[] objFileExtensions = new String[]{".o"}; + private static GccLibrarian instance = new GccLibrarian("ar", + objFileExtensions, false, new GccLibrarian("ar", objFileExtensions, + true, null)); + public static GccLibrarian getInstance() { + return instance; + } + private GccLibrarian(String command, String[] inputExtensions, + boolean isLibtool, GccLibrarian libtoolLibrarian) { + super(command, "V", inputExtensions, new String[0], "lib", ".a", + isLibtool, libtoolLibrarian); + } + protected Object clone() throws CloneNotSupportedException { + GccLibrarian clone = (GccLibrarian) super.clone(); + return clone; + } + public Linker getLinker(LinkType type) { + return GccLinker.getInstance().getLinker(type); + } + public void link(CCTask task, File outputFile, String[] sourceFiles, + CommandLineLinkerConfiguration config) throws BuildException { + try { + GccLibrarian clone = (GccLibrarian) this.clone(); + LinkerParam param = config.getParam("target"); + if (param != null) + clone.setCommand(param.getValue() + "-" + this.getCommand()); + clone.superlink(task, outputFile, sourceFiles, config); + } catch (CloneNotSupportedException e) { + superlink(task, outputFile, sourceFiles, config); + } + } + private void superlink(CCTask task, File outputFile, String[] sourceFiles, + CommandLineLinkerConfiguration config) throws BuildException { + super.link(task, outputFile, sourceFiles, config); + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/GccLinker.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/GccLinker.java new file mode 100755 index 0000000..4347211 --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/GccLinker.java @@ -0,0 +1,234 @@ +/* + * + * 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.gcc.cross; +import java.io.File; +import java.util.Vector; +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.LinkerParam; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinkerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.gcc.AbstractLdLinker; +import org.apache.tools.ant.BuildException; +/** + * Adapter for the GCC linker + * + * @author Adam Murdoch + */ +public class GccLinker extends AbstractLdLinker { + private static final String[] discardFiles = new String[0]; + private static final String[] objFiles = new String[]{".o", ".a", ".lib", + ".dll", ".so", ".sl"}; + private static final GccLinker dllLinker = new GccLinker("gcc", objFiles, + discardFiles, "lib", ".so", false, new GccLinker("gcc", objFiles, + discardFiles, "lib", ".so", true, null)); + private static final GccLinker instance = new GccLinker("gcc", objFiles, + discardFiles, "", "", false, null); + private static final String[] libtoolObjFiles = new String[]{".fo", ".a", + ".lib", ".dll", ".so", ".sl"}; + private static String[] linkerOptions = new String[]{"-bundle", + "-dynamiclib", "-nostartfiles", "-nostdlib", "-prebind", "-s", + "-static", "-shared", "-symbolic", "-Xlinker", + "--export-all-symbols", "-static-libgcc",}; + private static final GccLinker machBundleLinker = new GccLinker("gcc", + objFiles, discardFiles, "lib", ".bundle", false, null); + private static final GccLinker machDllLinker = new GccLinker("gcc", + objFiles, discardFiles, "lib", ".dylib", false, null); + public static GccLinker getInstance() { + return instance; + } + private File[] libDirs; + protected GccLinker(String command, String[] extensions, + String[] ignoredExtensions, String outputPrefix, + String outputSuffix, boolean isLibtool, GccLinker libtoolLinker) { + super(command, "-dumpversion", extensions, ignoredExtensions, + outputPrefix, outputSuffix, isLibtool, libtoolLinker); + } + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args) { + super.addImpliedArgs(debug, linkType, args); + if (getIdentifier().indexOf("mingw") >= 0) { + if (linkType.isSubsystemConsole()) { + args.addElement("-mconsole"); + } + if (linkType.isSubsystemGUI()) { + args.addElement("-mwindows"); + } + } + } + protected Object clone() throws CloneNotSupportedException { + GccLinker clone = (GccLinker) super.clone(); + return clone; + } + /** + * 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 + */ + public String decorateLinkerOption(StringBuffer buf, String arg) { + String decoratedArg = arg; + if (arg.length() > 1 && arg.charAt(0) == '-') { + switch (arg.charAt(1)) { + // + // passed automatically by GCC + // + case 'g' : + case 'f' : + case 'F' : + /* Darwin */ + case 'm' : + case 'O' : + case 'W' : + case 'l' : + case 'L' : + case 'u' : + case 'v' : + break; + default : + boolean known = false; + for (int i = 0; i < linkerOptions.length; i++) { + if (linkerOptions[i].equals(arg)) { + known = true; + break; + } + } + if (!known) { + buf.setLength(0); + buf.append("-Wl,"); + buf.append(arg); + decoratedArg = buf.toString(); + } + break; + } + } + return decoratedArg; + } + /** + * Returns library path. + * + */ + public File[] getLibraryPath() { + if (libDirs == null) { + // + // construct gcc lib path from machine and version + // + StringBuffer buf = new StringBuffer("/lib/gcc-lib/"); + buf.append(GccProcessor.getMachine()); + buf.append('/'); + buf.append(GccProcessor.getVersion()); + // + // build default path from gcc and system /lib and /lib/w32api + // + String[] impliedLibPath = new String[]{buf.toString(), + "/lib/w32api", "/lib"}; + // + // read gcc specs file for other library paths + // + String[] specs = GccProcessor.getSpecs(); + String[][] libpaths = GccProcessor.parseSpecs(specs, "*link:", + new String[]{"%q"}); + String[] libpath; + if (libpaths[0].length > 0) { + libpath = new String[libpaths[0].length + 3]; + int i = 0; + for (; i < libpaths[0].length; i++) { + libpath[i] = libpaths[0][i]; + } + libpath[i++] = buf.toString(); + libpath[i++] = "/lib/w32api"; + libpath[i++] = "/lib"; + } else { + // + // if a failure to find any matches then + // use some default values for lib path entries + libpath = new String[]{"/usr/local/lib/mingw", + "/usr/local/lib", "/usr/lib/w32api", "/usr/lib/mingw", + "/usr/lib", buf.toString(), "/lib/w32api", "/lib"}; + } + for (int i = 0; i < libpath.length; i++) { + if (libpath[i].indexOf("mingw") >= 0) { + libpath[i] = null; + } + } + // + // if cygwin then + // we have to prepend location of gcc32 + // and .. to start of absolute filenames to + // have something that will exist in the + // windows filesystem + if (GccProcessor.isCygwin()) { + GccProcessor.convertCygwinFilenames(libpath); + } + // + // check that remaining entries are actual directories + // + int count = CUtil.checkDirectoryArray(libpath); + // + // populate return array with remaining entries + // + libDirs = new File[count]; + int index = 0; + for (int i = 0; i < libpath.length; i++) { + if (libpath[i] != null) { + libDirs[index++] = new File(libpath[i]); + } + } + } + return libDirs; + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return GccLibrarian.getInstance(); + } + if (type.isPluginModule()) { + if (isDarwin()) { + return machBundleLinker; + } else { + return dllLinker; + } + } + if (type.isSharedLibrary()) { + if (isDarwin()) { + return machDllLinker; + } else { + return dllLinker; + } + } + return instance; + } + public void link(CCTask task, File outputFile, String[] sourceFiles, + CommandLineLinkerConfiguration config) throws BuildException { + try { + GccLinker clone = (GccLinker) this.clone(); + LinkerParam param = config.getParam("target"); + if (param != null) + clone.setCommand(param.getValue() + "-" + this.getCommand()); + clone.superlink(task, outputFile, sourceFiles, config); + } catch (CloneNotSupportedException e) { + superlink(task, outputFile, sourceFiles, config); + } + } + private void superlink(CCTask task, File outputFile, String[] sourceFiles, + CommandLineLinkerConfiguration config) throws BuildException { + super.link(task, outputFile, sourceFiles, config); + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/GccProcessor.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/GccProcessor.java new file mode 100755 index 0000000..8e35995 --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/GccProcessor.java @@ -0,0 +1,288 @@ +/* + * + * 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.gcc.cross; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CaptureStreamHandler; + +/** + * A add-in class for Gcc processors + * + * + */ +public class GccProcessor { + // the results from gcc -dumpmachine + private static String machine; + private static String[] specs; + // the results from gcc -dumpversion + private static String version; + private static int addLibraryPatterns(String[] libnames, StringBuffer buf, + String prefix, String extension, String[] patterns, int offset) { + for (int i = 0; i < libnames.length; i++) { + buf.setLength(0); + buf.append(prefix); + buf.append(libnames[i]); + buf.append(extension); + patterns[offset + i] = buf.toString(); + } + return offset + libnames.length; + } + /** + * Converts absolute Cygwin file or directory names to the corresponding + * Win32 name. + * + * @param names + * array of names, some elements may be null, will be changed in + * place. + */ + public static void convertCygwinFilenames(String[] names) { + if (names == null) { + throw new NullPointerException("names"); + } + File gccDir = CUtil.getExecutableLocation("gcc.exe"); + if (gccDir != null) { + String prefix = gccDir.getAbsolutePath() + "/.."; + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < names.length; i++) { + String name = names[i]; + if (name != null && name.length() > 1 && name.charAt(0) == '/') { + buf.setLength(0); + buf.append(prefix); + buf.append(name); + names[i] = buf.toString(); + } + } + } + } + + public static String getMachine() { + if (machine == null) { + String[] args = new String[]{"gcc", "-dumpmachine"}; + String[] cmdout = CaptureStreamHandler.run(args); + if (cmdout.length == 0) { + machine = "nomachine"; + } else { + machine = cmdout[0]; + } + } + return machine; + } + public static String[] getOutputFileSwitch(String letter, String outputFile) { + StringBuffer buf = new StringBuffer(); + if (outputFile.indexOf(' ') >= 0) { + buf.append('"'); + buf.append(outputFile.replace('\\', '/')); + buf.append('"'); + } else { + buf.append(outputFile.replace('\\', '/')); + } + String[] retval = new String[]{letter, buf.toString()}; + return retval; + } + /** + * Returns the contents of the gcc specs file. + * + * The implementation locates gcc.exe in the executable path and then + * builds a relative path name from the results of -dumpmachine and + * -dumpversion. Attempts to use gcc -dumpspecs to provide this information + * resulted in stalling on the Execute.run + * + * @returns contents of the specs file + */ + public static String[] getSpecs() { + if (specs == null) { + File gccParent = CUtil.getExecutableLocation("gcc.exe"); + if (gccParent != null) { + // + // build a relative path like + // ../lib/gcc-lib/i686-pc-cygwin/2.95.3-5/specs + // + StringBuffer buf = new StringBuffer("../lib/gcc-lib/"); + buf.append(getMachine()); + buf.append('/'); + buf.append(getVersion()); + buf.append("/specs"); + // + // resolve it relative to the location of gcc.exe + // + String relativePath = buf.toString(); + File specsFile = new File(gccParent, relativePath); + // + // found the specs file + // + try { + // + // read the lines in the file + // + BufferedReader reader = new BufferedReader(new FileReader( + specsFile)); + Vector lines = new Vector(100); + String line = reader.readLine(); + while (line != null) { + lines.addElement(line); + line = reader.readLine(); + } + specs = new String[lines.size()]; + lines.copyInto(specs); + } catch (IOException ex) { + } + } + } + if (specs == null) { + specs = new String[0]; + } + return specs; + } + public static String getVersion() { + if (version == null) { + String[] args = new String[]{"gcc", "-dumpversion"}; + String[] cmdout = CaptureStreamHandler.run(args); + if (cmdout.length == 0) { + version = "noversion"; + } else { + version = cmdout[0]; + } + } + return version; + } + public static boolean isCaseSensitive() { + return true; + } + /** + * Determines if task is running with cygwin + * + * @return true if cygwin was detected + */ + public static boolean isCygwin() { + return getMachine().indexOf("cygwin") > 0; + } + private static boolean isHPUX() { + String osname = System.getProperty("os.name").toLowerCase(); + if (osname.indexOf("hp") >= 0 && osname.indexOf("ux") >= 0) { + return true; + } + return false; + } + /** + * + * Parses the results of the specs file for a specific processor and + * options + * + * @param specsContent + * Contents of specs file as returned from getSpecs + * @param specSectionStart + * start of spec section, for example "*cpp:" + * @param options + * command line switches such as "-istart" + */ + public static String[][] parseSpecs(String[] specsContent, + String specSectionStart, String[] options) { + if (specsContent == null) { + throw new NullPointerException("specsContent"); + } + if (specSectionStart == null) { + throw new NullPointerException("specSectionStart"); + } + if (options == null) { + throw new NullPointerException("option"); + } + String[][] optionValues = new String[options.length][]; + StringBuffer optionValue = new StringBuffer(40); + for (int i = 0; i < specsContent.length; i++) { + String specLine = specsContent[i]; + // + // if start of section then start paying attention + // + if (specLine.startsWith(specSectionStart)) { + Vector[] optionVectors = new Vector[options.length]; + for (int j = 0; j < options.length; j++) { + optionVectors[j] = new Vector(10); + } + // + // go to next line and examine contents + // and repeat until end of file + // + for (i++; i < specsContent.length; i++) { + specLine = specsContent[i]; + for (int j = 0; j < options.length; j++) { + int optionStart = specLine.indexOf(options[j]); + while (optionStart >= 0) { + optionValue.setLength(0); + // + // walk rest of line looking for first non + // whitespace + // and then next space + boolean hasNonBlank = false; + int k = optionStart + options[j].length(); + for (; k < specLine.length(); k++) { + // + // either a blank or a "}" (close of + // conditional) + // section will end the path + // + if (specLine.charAt(k) == ' ' + || specLine.charAt(k) == '}') { + if (hasNonBlank) { + break; + } + } else { + hasNonBlank = true; + optionValue.append(specLine.charAt(k)); + } + } + // + // transition back to whitespace + // value is over, add it to vector + if (hasNonBlank) { + optionVectors[j].addElement(optionValue + .toString()); + } + // + // find next occurance on line + // + optionStart = specLine.indexOf(options[j], k); + } + } + } + // + // copy vectors over to option arrays + // + for (int j = 0; j < options.length; j++) { + optionValues[j] = new String[optionVectors[j].size()]; + optionVectors[j].copyInto(optionValues[j]); + } + } + } + // + // fill in any missing option values with + // a zero-length string array + for (int i = 0; i < optionValues.length; i++) { + String[] zeroLenArray = new String[0]; + if (optionValues[i] == null) { + optionValues[i] = zeroLenArray; + } + } + return optionValues; + } + private GccProcessor() { + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/GppLinker.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/GppLinker.java new file mode 100755 index 0000000..b332c64 --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/GppLinker.java @@ -0,0 +1,228 @@ +/* + * + * Copyright 2003-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.gcc.cross; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.LinkerParam; +import net.sf.antcontrib.cpptasks.compiler.CaptureStreamHandler; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinkerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.gcc.AbstractLdLinker; +import net.sf.antcontrib.cpptasks.types.LibrarySet; + +import org.apache.tools.ant.BuildException; +/** + * Adapter for the g++ variant of the GCC linker + * + * @author Stephen M. Webb <[email protected]> + */ +public class GppLinker extends AbstractLdLinker { + protected static final String[] discardFiles = new String[0]; + protected static final String[] objFiles = new String[]{".o", ".a", ".lib", + ".dll", ".so", ".sl"}; + private static final GppLinker dllLinker = new GppLinker("gcc", objFiles, + discardFiles, "lib", ".so", false, new GppLinker("gcc", objFiles, + discardFiles, "lib", ".so", true, null)); + private final static String libPrefix = "libraries: ="; + protected static final String[] libtoolObjFiles = new String[]{".fo", ".a", + ".lib", ".dll", ".so", ".sl"}; + private static String[] linkerOptions = new String[]{"-bundle", "-dylib", + "-dynamic", "-dynamiclib", "-nostartfiles", "-nostdlib", + "-prebind", "-s", "-static", "-shared", "-symbolic", "-Xlinker"}; + private static final GppLinker instance = new GppLinker("gcc", objFiles, + discardFiles, "", "", false, null); + private static final GppLinker machDllLinker = new GppLinker("gcc", + objFiles, discardFiles, "lib", ".dylib", false, null); + private static final GppLinker machPluginLinker = new GppLinker("gcc", + objFiles, discardFiles, "lib", ".bundle", false, null); + public static GppLinker getInstance() { + return instance; + } + private File[] libDirs; + private String runtimeLibrary; + protected GppLinker(String command, String[] extensions, + String[] ignoredExtensions, String outputPrefix, + String outputSuffix, boolean isLibtool, GppLinker libtoolLinker) { + super(command, "-dumpversion", extensions, ignoredExtensions, + outputPrefix, outputSuffix, isLibtool, libtoolLinker); + } + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args) { + super.addImpliedArgs(debug, linkType, args); + if (getIdentifier().indexOf("mingw") >= 0) { + if (linkType.isSubsystemConsole()) { + args.addElement("-mconsole"); + } + if (linkType.isSubsystemGUI()) { + args.addElement("-mwindows"); + } + } + if (linkType.isStaticRuntime()) { + String[] cmdin = new String[]{"g++", "-print-file-name=libstdc++.a"}; + String[] cmdout = CaptureStreamHandler.run(cmdin); + if (cmdout.length > 0) { + runtimeLibrary = cmdout[0]; + } else { + runtimeLibrary = null; + } + } else { + runtimeLibrary = "-lstdc++"; + } + } + public String[] addLibrarySets(CCTask task, LibrarySet[] libsets, + Vector preargs, Vector midargs, Vector endargs) { + String[] rs = super.addLibrarySets(task, libsets, preargs, midargs, + endargs); + if (runtimeLibrary != null) { + endargs.addElement(runtimeLibrary); + } + return rs; + } + protected Object clone() throws CloneNotSupportedException { + GppLinker clone = (GppLinker) super.clone(); + return clone; + } + /** + * Allows drived linker to decorate linker option. Override by GppLinker 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 + */ + public String decorateLinkerOption(StringBuffer buf, String arg) { + String decoratedArg = arg; + if (arg.length() > 1 && arg.charAt(0) == '-') { + switch (arg.charAt(1)) { + // + // passed automatically by GCC + // + case 'g' : + case 'f' : + case 'F' : + /* Darwin */ + case 'm' : + case 'O' : + case 'W' : + case 'l' : + case 'L' : + case 'u' : + break; + default : + boolean known = false; + for (int i = 0; i < linkerOptions.length; i++) { + if (linkerOptions[i].equals(arg)) { + known = true; + break; + } + } + if (!known) { + buf.setLength(0); + buf.append("-Wl,"); + buf.append(arg); + decoratedArg = buf.toString(); + } + break; + } + } + return decoratedArg; + } + /** + * Returns library path. + * + */ + public File[] getLibraryPath() { + if (libDirs == null) { + Vector dirs = new Vector(); + // Ask GCC where it will look for its libraries. + String[] args = new String[]{"g++", "-print-search-dirs"}; + String[] cmdout = CaptureStreamHandler.run(args); + for (int i = 0; i < cmdout.length; ++i) { + int prefixIndex = cmdout[i].indexOf(libPrefix); + if (prefixIndex >= 0) { + // Special case DOS-type GCCs like MinGW or Cygwin + int s = prefixIndex + libPrefix.length(); + int t = cmdout[i].indexOf(';', s); + while (t > 0) { + dirs.addElement(cmdout[i].substring(s, t)); + s = t + 1; + t = cmdout[i].indexOf(';', s); + } + dirs.addElement(cmdout[i].substring(s)); + ++i; + for (; i < cmdout.length; ++i) { + dirs.addElement(cmdout[i]); + } + } + } + // Eliminate all but actual directories. + String[] libpath = new String[dirs.size()]; + dirs.copyInto(libpath); + int count = CUtil.checkDirectoryArray(libpath); + // Build return array. + libDirs = new File[count]; + int index = 0; + for (int i = 0; i < libpath.length; ++i) { + if (libpath[i] != null) { + libDirs[index++] = new File(libpath[i]); + } + } + } + return libDirs; + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return GccLibrarian.getInstance(); + } + if (type.isPluginModule()) { + if (GccProcessor.getMachine().indexOf("darwin") >= 0) { + return machPluginLinker; + } else { + return dllLinker; + } + } + if (type.isSharedLibrary()) { + if (GccProcessor.getMachine().indexOf("darwin") >= 0) { + return machDllLinker; + } else { + return dllLinker; + } + } + return instance; + } + public void link(CCTask task, File outputFile, String[] sourceFiles, + CommandLineLinkerConfiguration config) throws BuildException { + try { + GppLinker clone = (GppLinker) this.clone(); + LinkerParam param = config.getParam("target"); + if (param != null) + clone.setCommand(param.getValue() + "-" + this.getCommand()); + clone.superlink(task, outputFile, sourceFiles, config); + } catch (CloneNotSupportedException e) { + superlink(task, outputFile, sourceFiles, config); + } + } + private void superlink(CCTask task, File outputFile, String[] sourceFiles, + CommandLineLinkerConfiguration config) throws BuildException { + super.link(task, outputFile, sourceFiles, config); + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/LdLinker.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/LdLinker.java new file mode 100755 index 0000000..26abf8c --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/LdLinker.java @@ -0,0 +1,83 @@ +/* + * + * 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.gcc.cross; +import java.io.File; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.LinkerParam; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinkerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.gcc.AbstractLdLinker; + +import org.apache.tools.ant.BuildException; +/** + * Adapter for the 'ld' linker + * + * @author Curt Arnold + */ +public final class LdLinker extends AbstractLdLinker { + private static final String[] libtoolObjFiles = new String[]{".fo", ".a", + ".lib", ".dll", ".so", ".sl"}; + private static final String[] objFiles = new String[]{".o", ".a", ".lib", + ".dll", ".so", ".sl"}; + private static final String[] discardFiles = new String[0]; + private static final LdLinker dllLinker = new LdLinker("ld", objFiles, + discardFiles, "lib", ".so", false, new LdLinker("ld", objFiles, + discardFiles, "lib", ".so", true, null)); + private static final LdLinker instance = new LdLinker("ld", objFiles, + discardFiles, "", "", false, null); + public static LdLinker getInstance() { + return instance; + } + private File[] libDirs; + private LdLinker(String command, String[] extensions, + String[] ignoredExtensions, String outputPrefix, + String outputSuffix, boolean isLibtool, LdLinker libtoolLinker) { + super(command, "-version", extensions, ignoredExtensions, outputPrefix, + outputSuffix, isLibtool, libtoolLinker); + } + protected Object clone() throws CloneNotSupportedException { + LdLinker clone = (LdLinker) super.clone(); + return clone; + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return GccLibrarian.getInstance(); + } + if (type.isSharedLibrary()) { + return dllLinker; + } + return instance; + } + public void link(CCTask task, File outputFile, String[] sourceFiles, + CommandLineLinkerConfiguration config) throws BuildException { + try { + LdLinker clone = (LdLinker) this.clone(); + LinkerParam param = config.getParam("target"); + if (param != null) + clone.setCommand(param.getValue() + "-" + this.getCommand()); + clone.superlink(task, outputFile, sourceFiles, config); + } catch (CloneNotSupportedException e) { + superlink(task, outputFile, sourceFiles, config); + } + } + private void superlink(CCTask task, File outputFile, String[] sourceFiles, + CommandLineLinkerConfiguration config) throws BuildException { + super.link(task, outputFile, sourceFiles, config); + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccCCompiler.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccCCompiler.java new file mode 100755 index 0000000..44dd968 --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccCCompiler.java @@ -0,0 +1,244 @@ +/* + * + * 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.gcc.cross.sparc_sun_solaris2; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.compiler.Processor; +import net.sf.antcontrib.cpptasks.gcc.GccCompatibleCCompiler; +import net.sf.antcontrib.cpptasks.parser.CParser; +import net.sf.antcontrib.cpptasks.parser.FortranParser; +import net.sf.antcontrib.cpptasks.parser.Parser; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.types.Environment; +import net.sf.antcontrib.cpptasks.OptimizationEnum; + +/** + * Adapter for the GCC C/C++ compiler + * + * @author Adam Murdoch + */ +public final class GccCCompiler extends GccCompatibleCCompiler { + private final static String[] sourceExtensions = new String[]{".c", /* C */ + ".cc", /* C++ */ + ".cpp", /* C++ */ + ".cxx", /* C++ */ + ".c++", /* C++ */ + ".i", /* preprocessed C */ + ".ii", /* preprocessed C++ */ + ".f", /* FORTRAN */ + ".for", /* FORTRAN */ + ".m", /* Objective-C */ + ".mm", /* Objected-C++ */ + ".s" /* Assembly */ + }; + private final static String[] headerExtensions = new String[]{".h", ".hpp", + ".inl"}; + public static final String CMD_PREFIX = "sparc-sun-solaris2-"; + private static final GccCCompiler cppInstance = new GccCCompiler(CMD_PREFIX + + "c++", sourceExtensions, headerExtensions, false, + new GccCCompiler(CMD_PREFIX + "c++", sourceExtensions, + headerExtensions, true, null, false, null), false, null); + private static final GccCCompiler g77Instance = new GccCCompiler(CMD_PREFIX + + "g77", sourceExtensions, headerExtensions, false, + new GccCCompiler(CMD_PREFIX + "g77", sourceExtensions, + headerExtensions, true, null, false, null), false, null); + private static final GccCCompiler gppInstance = new GccCCompiler(CMD_PREFIX + + "g++", sourceExtensions, headerExtensions, false, + new GccCCompiler(CMD_PREFIX + "g++", sourceExtensions, + headerExtensions, true, null, false, null), false, null); + private static final GccCCompiler instance = new GccCCompiler(CMD_PREFIX + + "gcc", sourceExtensions, headerExtensions, false, + new GccCCompiler(CMD_PREFIX + "gcc", sourceExtensions, + headerExtensions, true, null, false, null), false, null); + /** + * Gets c++ adapter + */ + public static GccCCompiler getCppInstance() { + return cppInstance; + } + /** + * Gets g77 adapter + */ + public static GccCCompiler getG77Instance() { + return g77Instance; + } + /** + * Gets gpp adapter + */ + public static GccCCompiler getGppInstance() { + return gppInstance; + } + /** + * Gets gcc adapter + */ + public static GccCCompiler getInstance() { + return instance; + } + private String identifier; + private File[] includePath; + private boolean isPICMeaningful = true; + /** + * Private constructor. Use GccCCompiler.getInstance() to get singleton + * instance of this class. + */ + private GccCCompiler(String command, String[] sourceExtensions, + String[] headerExtensions, boolean isLibtool, + GccCCompiler libtoolCompiler, boolean newEnvironment, + Environment env) { + super(command, null, sourceExtensions, headerExtensions, isLibtool, + libtoolCompiler, newEnvironment, env); + isPICMeaningful = System.getProperty("os.name").indexOf("Windows") < 0; + } + public void addImpliedArgs(final Vector args, + final boolean debug, + final boolean multithreaded, + final boolean exceptions, + final LinkType linkType, + final Boolean rtti, + final OptimizationEnum optimization) { + super.addImpliedArgs(args, debug, multithreaded, + exceptions, linkType, rtti, optimization); + if (isPICMeaningful && linkType.isSharedLibrary()) { + args.addElement("-fPIC"); + } + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + if (newEnvironment || env != null) { + return new GccCCompiler(getCommand(), this.getSourceExtensions(), + this.getHeaderExtensions(), this.getLibtool(), + (GccCCompiler) this.getLibtoolCompiler(), newEnvironment, + env); + } + return this; + } + /** + * Create parser to determine dependencies. + * + * Will create appropriate parser (C++, FORTRAN) based on file extension. + * + */ + protected Parser createParser(File source) { + if (source != null) { + String sourceName = source.getName(); + int lastDot = sourceName.lastIndexOf('.'); + if (lastDot >= 0 && lastDot + 1 < sourceName.length()) { + char afterDot = sourceName.charAt(lastDot + 1); + if (afterDot == 'f' || afterDot == 'F') { + return new FortranParser(); + } + } + } + return new CParser(); + } + public File[] getEnvironmentIncludePath() { + if (includePath == null) { + // + // construct default include path from machine id and version id + // + String[] defaultInclude = new String[1]; + StringBuffer buf = new StringBuffer("/lib/"); + buf.append(GccProcessor.getMachine()); + buf.append('/'); + buf.append(GccProcessor.getVersion()); + buf.append("/include"); + defaultInclude[0] = buf.toString(); + // + // read specs file and look for -istart and -idirafter + // + String[] specs = GccProcessor.getSpecs(); + String[][] optionValues = GccProcessor.parseSpecs(specs, "*cpp:", + new String[]{"-isystem ", "-idirafter "}); + // + // if no entries were found, then use a default path + // + if (optionValues[0].length == 0 && optionValues[1].length == 0) { + optionValues[0] = new String[]{"/usr/local/include", + "/usr/include", "/usr/include/win32api"}; + } + // + // remove mingw entries. + // For MinGW compiles this will mean the + // location of the sys includes will be + // wrong in dependencies.xml + // but that should have no significant effect + for (int i = 0; i < optionValues.length; i++) { + for (int j = 0; j < optionValues[i].length; j++) { + if (optionValues[i][j].indexOf("mingw") > 0) { + optionValues[i][j] = null; + } + } + } + // + // if cygwin then + // we have to prepend location of gcc32 + // and .. to start of absolute filenames to + // have something that will exist in the + // windows filesystem + if (GccProcessor.isCygwin()) { + GccProcessor.convertCygwinFilenames(optionValues[0]); + GccProcessor.convertCygwinFilenames(optionValues[1]); + GccProcessor.convertCygwinFilenames(defaultInclude); + } + int count = CUtil.checkDirectoryArray(optionValues[0]); + count += CUtil.checkDirectoryArray(optionValues[1]); + count += CUtil.checkDirectoryArray(defaultInclude); + includePath = new File[count]; + int index = 0; + for (int i = 0; i < optionValues.length; i++) { + for (int j = 0; j < optionValues[i].length; j++) { + if (optionValues[i][j] != null) { + includePath[index++] = new File(optionValues[i][j]); + } + } + } + for (int i = 0; i < defaultInclude.length; i++) { + if (defaultInclude[i] != null) { + includePath[index++] = new File(defaultInclude[i]); + } + } + } + return (File[]) includePath.clone(); + } + public String getIdentifier() throws BuildException { + if (identifier == null) { + StringBuffer buf; + if (getLibtool()) { + buf = new StringBuffer("libtool "); + } else { + buf = new StringBuffer(' '); + } + buf.append(getCommand()); + buf.append(' '); + buf.append(GccProcessor.getVersion()); + buf.append(' '); + buf.append(GccProcessor.getMachine()); + identifier = buf.toString(); + } + return identifier; + } + public Linker getLinker(LinkType linkType) { + return GccLinker.getInstance().getLinker(linkType); + } + public int getMaximumCommandLength() { + return Integer.MAX_VALUE; + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccLibrarian.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccLibrarian.java new file mode 100755 index 0000000..779fb3d --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccLibrarian.java @@ -0,0 +1,43 @@ +/* + * + * 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.gcc.cross.sparc_sun_solaris2; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.gcc.AbstractArLibrarian; +/** + * Adapter for the 'ar' archiver + * + * @author Adam Murdoch + */ +public final class GccLibrarian extends AbstractArLibrarian { + private static String[] objFileExtensions = new String[]{".o"}; + private static GccLibrarian instance = new GccLibrarian( + GccCCompiler.CMD_PREFIX + "ar", objFileExtensions, false, + new GccLibrarian(GccCCompiler.CMD_PREFIX + "ar", objFileExtensions, + true, null)); + public static GccLibrarian getInstance() { + return instance; + } + private GccLibrarian(String command, String[] inputExtensions, + boolean isLibtool, GccLibrarian libtoolLibrarian) { + super(command, "V", inputExtensions, new String[0], "lib", ".a", + isLibtool, libtoolLibrarian); + } + public Linker getLinker(LinkType type) { + return GccLinker.getInstance().getLinker(type); + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccLinker.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccLinker.java new file mode 100755 index 0000000..d7dd3db --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccLinker.java @@ -0,0 +1,215 @@ +/* + * + * 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.gcc.cross.sparc_sun_solaris2; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.gcc.AbstractLdLinker; +/** + * Adapter for the GCC linker + * + * @author Adam Murdoch + */ +public class GccLinker extends AbstractLdLinker { + private static final String[] discardFiles = new String[0]; + private static final String[] objFiles = new String[]{".o", ".a", ".lib", + ".dll", ".so", ".sl"}; + private static final String[] libtoolObjFiles = new String[]{".fo", ".a", + ".lib", ".dll", ".so", ".sl"}; + private static String[] linkerOptions = new String[]{"-bundle", + "-dynamiclib", "-nostartfiles", "-nostdlib", "-prebind", "-s", + "-static", "-shared", "-symbolic", "-Xlinker", + "--export-all-symbols", "-static-libgcc",}; + private static final GccLinker dllLinker = new GccLinker( + GccCCompiler.CMD_PREFIX + "gcc", objFiles, discardFiles, "lib", + ".so", false, new GccLinker(GccCCompiler.CMD_PREFIX + "gcc", + objFiles, discardFiles, "lib", ".so", true, null)); + private static final GccLinker instance = new GccLinker( + GccCCompiler.CMD_PREFIX + "gcc", objFiles, discardFiles, "", "", + false, null); + private static final GccLinker machBundleLinker = new GccLinker( + GccCCompiler.CMD_PREFIX + "gcc", objFiles, discardFiles, "lib", + ".bundle", false, null); + private static final GccLinker machDllLinker = new GccLinker( + GccCCompiler.CMD_PREFIX + "gcc", objFiles, discardFiles, "lib", + ".dylib", false, null); + public static GccLinker getInstance() { + return instance; + } + private File[] libDirs; + protected GccLinker(String command, String[] extensions, + String[] ignoredExtensions, String outputPrefix, + String outputSuffix, boolean isLibtool, GccLinker libtoolLinker) { + super(command, "-dumpversion", extensions, ignoredExtensions, + outputPrefix, outputSuffix, isLibtool, libtoolLinker); + } + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args) { + super.addImpliedArgs(debug, linkType, args); + if (getIdentifier().indexOf("mingw") >= 0) { + if (linkType.isSubsystemConsole()) { + args.addElement("-mconsole"); + } + if (linkType.isSubsystemGUI()) { + args.addElement("-mwindows"); + } + } + } + /** + * 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 + */ + public String decorateLinkerOption(StringBuffer buf, String arg) { + String decoratedArg = arg; + if (arg.length() > 1 && arg.charAt(0) == '-') { + switch (arg.charAt(1)) { + // + // passed automatically by GCC + // + case 'g' : + case 'f' : + case 'F' : + /* Darwin */ + case 'm' : + case 'O' : + case 'W' : + case 'l' : + case 'L' : + case 'u' : + case 'v' : + break; + default : + boolean known = false; + for (int i = 0; i < linkerOptions.length; i++) { + if (linkerOptions[i].equals(arg)) { + known = true; + break; + } + } + if (!known) { + buf.setLength(0); + buf.append("-Wl,"); + buf.append(arg); + decoratedArg = buf.toString(); + } + break; + } + } + return decoratedArg; + } + /** + * Returns library path. + * + */ + public File[] getLibraryPath() { + if (libDirs == null) { + // + // construct gcc lib path from machine and version + // + StringBuffer buf = new StringBuffer("/lib/gcc-lib/"); + buf.append(GccProcessor.getMachine()); + buf.append('/'); + buf.append(GccProcessor.getVersion()); + // + // build default path from gcc and system /lib and /lib/w32api + // + String[] impliedLibPath = new String[]{buf.toString(), + "/lib/w32api", "/lib"}; + // + // read gcc specs file for other library paths + // + String[] specs = GccProcessor.getSpecs(); + String[][] libpaths = GccProcessor.parseSpecs(specs, "*link:", + new String[]{"%q"}); + String[] libpath; + if (libpaths[0].length > 0) { + libpath = new String[libpaths[0].length + 3]; + int i = 0; + for (; i < libpaths[0].length; i++) { + libpath[i] = libpaths[0][i]; + } + libpath[i++] = buf.toString(); + libpath[i++] = "/lib/w32api"; + libpath[i++] = "/lib"; + } else { + // + // if a failure to find any matches then + // use some default values for lib path entries + libpath = new String[]{"/usr/local/lib/mingw", + "/usr/local/lib", "/usr/lib/w32api", "/usr/lib/mingw", + "/usr/lib", buf.toString(), "/lib/w32api", "/lib"}; + } + for (int i = 0; i < libpath.length; i++) { + if (libpath[i].indexOf("mingw") >= 0) { + libpath[i] = null; + } + } + // + // if cygwin then + // we have to prepend location of gcc32 + // and .. to start of absolute filenames to + // have something that will exist in the + // windows filesystem + if (GccProcessor.isCygwin()) { + GccProcessor.convertCygwinFilenames(libpath); + } + // + // check that remaining entries are actual directories + // + int count = CUtil.checkDirectoryArray(libpath); + // + // populate return array with remaining entries + // + libDirs = new File[count]; + int index = 0; + for (int i = 0; i < libpath.length; i++) { + if (libpath[i] != null) { + libDirs[index++] = new File(libpath[i]); + } + } + } + return libDirs; + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return GccLibrarian.getInstance(); + } + if (type.isPluginModule()) { + if (isDarwin()) { + return machBundleLinker; + } else { + return dllLinker; + } + } + if (type.isSharedLibrary()) { + if (isDarwin()) { + return machDllLinker; + } else { + return dllLinker; + } + } + return instance; + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccProcessor.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccProcessor.java new file mode 100755 index 0000000..8a7a26e --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccProcessor.java @@ -0,0 +1,305 @@ +/* + * + * 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.gcc.cross.sparc_sun_solaris2; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CaptureStreamHandler; +import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum; + +/** + * A add-in class for Gcc processors + * + * + */ +public class GccProcessor { + // the results from gcc -dumpmachine + private static String machine; + private static String[] specs; + // the results from gcc -dumpversion + private static String version; + private static int addLibraryPatterns(String[] libnames, StringBuffer buf, + String prefix, String extension, String[] patterns, int offset) { + for (int i = 0; i < libnames.length; i++) { + buf.setLength(0); + buf.append(prefix); + buf.append(libnames[i]); + buf.append(extension); + patterns[offset + i] = buf.toString(); + } + return offset + libnames.length; + } + /** + * Converts absolute Cygwin file or directory names to the corresponding + * Win32 name. + * + * @param names + * array of names, some elements may be null, will be changed in + * place. + */ + public static void convertCygwinFilenames(String[] names) { + if (names == null) { + throw new NullPointerException("names"); + } + File gccDir = CUtil.getExecutableLocation(GccCCompiler.CMD_PREFIX + + "gcc.exe"); + if (gccDir != null) { + String prefix = gccDir.getAbsolutePath() + "/.."; + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < names.length; i++) { + String name = names[i]; + if (name != null && name.length() > 1 && name.charAt(0) == '/') { + buf.setLength(0); + buf.append(prefix); + buf.append(name); + names[i] = buf.toString(); + } + } + } + } + public static String[] getLibraryPatterns(String[] libnames, LibraryTypeEnum libType) { + StringBuffer buf = new StringBuffer(); + String[] patterns = new String[libnames.length * 2]; + int offset = addLibraryPatterns(libnames, buf, "lib", ".a", patterns, 0); + if (isHPUX()) { + offset = addLibraryPatterns(libnames, buf, "lib", ".sl", patterns, + offset); + } else { + offset = addLibraryPatterns(libnames, buf, "lib", ".so", patterns, + offset); + } + return patterns; + } + public static String getMachine() { + if (machine == null) { + String[] args = new String[]{GccCCompiler.CMD_PREFIX + "gcc", + "-dumpmachine"}; + String[] cmdout = CaptureStreamHandler.run(args); + if (cmdout.length == 0) { + machine = "nomachine"; + } else { + machine = cmdout[0]; + } + } + return machine; + } + public static String[] getOutputFileSwitch(String letter, String outputFile) { + StringBuffer buf = new StringBuffer(); + if (outputFile.indexOf(' ') >= 0) { + buf.append('"'); + buf.append(outputFile.replace('\\', '/')); + buf.append('"'); + } else { + buf.append(outputFile.replace('\\', '/')); + } + String[] retval = new String[]{letter, buf.toString()}; + return retval; + } + /** + * Returns the contents of the gcc specs file. + * + * The implementation locates gcc.exe in the executable path and then + * builds a relative path name from the results of -dumpmachine and + * -dumpversion. Attempts to use gcc -dumpspecs to provide this information + * resulted in stalling on the Execute.run + * + * @returns contents of the specs file + */ + public static String[] getSpecs() { + if (specs == null) { + File gccParent = CUtil + .getExecutableLocation(GccCCompiler.CMD_PREFIX + "gcc.exe"); + if (gccParent != null) { + // + // build a relative path like + // ../lib/gcc-lib/i686-pc-cygwin/2.95.3-5/specs + // + StringBuffer buf = new StringBuffer("../lib/gcc-lib/"); + buf.append(getMachine()); + buf.append('/'); + buf.append(getVersion()); + buf.append("/specs"); + // + // resolve it relative to the location of gcc.exe + // + String relativePath = buf.toString(); + File specsFile = new File(gccParent, relativePath); + // + // found the specs file + // + try { + // + // read the lines in the file + // + BufferedReader reader = new BufferedReader(new FileReader( + specsFile)); + Vector lines = new Vector(100); + String line = reader.readLine(); + while (line != null) { + lines.addElement(line); + line = reader.readLine(); + } + specs = new String[lines.size()]; + lines.copyInto(specs); + } catch (IOException ex) { + } + } + } + if (specs == null) { + specs = new String[0]; + } + return specs; + } + public static String getVersion() { + if (version == null) { + String[] args = new String[]{GccCCompiler.CMD_PREFIX + "gcc", + "-dumpversion"}; + String[] cmdout = CaptureStreamHandler.run(args); + if (cmdout.length == 0) { + version = "noversion"; + } else { + version = cmdout[0]; + } + } + return version; + } + public static boolean isCaseSensitive() { + return true; + } + /** + * Determines if task is running with cygwin + * + * @return true if cygwin was detected + */ + public static boolean isCygwin() { + return getMachine().indexOf("cygwin") > 0; + } + private static boolean isHPUX() { + String osname = System.getProperty("os.name").toLowerCase(); + if (osname.indexOf("hp") >= 0 && osname.indexOf("ux") >= 0) { + return true; + } + return false; + } + /** + * + * Parses the results of the specs file for a specific processor and + * options + * + * @param specsContent + * Contents of specs file as returned from getSpecs + * @param specSectionStart + * start of spec section, for example "*cpp:" + * @param options + * command line switches such as "-istart" + */ + public static String[][] parseSpecs(String[] specsContent, + String specSectionStart, String[] options) { + if (specsContent == null) { + throw new NullPointerException("specsContent"); + } + if (specSectionStart == null) { + throw new NullPointerException("specSectionStart"); + } + if (options == null) { + throw new NullPointerException("option"); + } + String[][] optionValues = new String[options.length][]; + StringBuffer optionValue = new StringBuffer(40); + for (int i = 0; i < specsContent.length; i++) { + String specLine = specsContent[i]; + // + // if start of section then start paying attention + // + if (specLine.startsWith(specSectionStart)) { + Vector[] optionVectors = new Vector[options.length]; + for (int j = 0; j < options.length; j++) { + optionVectors[j] = new Vector(10); + } + // + // go to next line and examine contents + // and repeat until end of file + // + for (i++; i < specsContent.length; i++) { + specLine = specsContent[i]; + for (int j = 0; j < options.length; j++) { + int optionStart = specLine.indexOf(options[j]); + while (optionStart >= 0) { + optionValue.setLength(0); + // + // walk rest of line looking for first non + // whitespace + // and then next space + boolean hasNonBlank = false; + int k = optionStart + options[j].length(); + for (; k < specLine.length(); k++) { + // + // either a blank or a "}" (close of + // conditional) + // section will end the path + // + if (specLine.charAt(k) == ' ' + || specLine.charAt(k) == '}') { + if (hasNonBlank) { + break; + } + } else { + hasNonBlank = true; + optionValue.append(specLine.charAt(k)); + } + } + // + // transition back to whitespace + // value is over, add it to vector + if (hasNonBlank) { + optionVectors[j].addElement(optionValue + .toString()); + } + // + // find next occurance on line + // + optionStart = specLine.indexOf(options[j], k); + } + } + } + // + // copy vectors over to option arrays + // + for (int j = 0; j < options.length; j++) { + optionValues[j] = new String[optionVectors[j].size()]; + optionVectors[j].copyInto(optionValues[j]); + } + } + } + // + // fill in any missing option values with + // a zero-length string array + for (int i = 0; i < optionValues.length; i++) { + String[] zeroLenArray = new String[0]; + if (optionValues[i] == null) { + optionValues[i] = zeroLenArray; + } + } + return optionValues; + } + private GccProcessor() { + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GppLinker.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GppLinker.java new file mode 100755 index 0000000..45bbea9 --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GppLinker.java @@ -0,0 +1,210 @@ +/* + * + * Copyright 2003-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.gcc.cross.sparc_sun_solaris2; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CaptureStreamHandler; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.gcc.AbstractLdLinker; +import net.sf.antcontrib.cpptasks.types.LibrarySet; +/** + * Adapter for the g++ variant of the GCC linker + * + * @author Stephen M. Webb <[email protected]> + */ +public class GppLinker extends AbstractLdLinker { + protected static final String[] discardFiles = new String[0]; + protected static final String[] objFiles = new String[]{".o", ".a", ".lib", + ".dll", ".so", ".sl"}; + private final static String libPrefix = "libraries: ="; + protected static final String[] libtoolObjFiles = new String[]{".fo", ".a", + ".lib", ".dll", ".so", ".sl"}; + private static String[] linkerOptions = new String[]{"-bundle", "-dylib", + "-dynamic", "-dynamiclib", "-nostartfiles", "-nostdlib", + "-prebind", "-s", "-static", "-shared", "-symbolic", "-Xlinker"}; + private static final GppLinker dllLinker = new GppLinker( + GccCCompiler.CMD_PREFIX + "gcc", objFiles, discardFiles, "lib", + ".so", false, new GppLinker(GccCCompiler.CMD_PREFIX + "gcc", + objFiles, discardFiles, "lib", ".so", true, null)); + private static final GppLinker instance = new GppLinker( + GccCCompiler.CMD_PREFIX + "gcc", objFiles, discardFiles, "", "", + false, null); + private static final GppLinker machDllLinker = new GppLinker( + GccCCompiler.CMD_PREFIX + "gcc", objFiles, discardFiles, "lib", + ".dylib", false, null); + private static final GppLinker machPluginLinker = new GppLinker( + GccCCompiler.CMD_PREFIX + "gcc", objFiles, discardFiles, "lib", + ".bundle", false, null); + public static GppLinker getInstance() { + return instance; + } + private File[] libDirs; + private String runtimeLibrary; + protected GppLinker(String command, String[] extensions, + String[] ignoredExtensions, String outputPrefix, + String outputSuffix, boolean isLibtool, GppLinker libtoolLinker) { + super(command, "-dumpversion", extensions, ignoredExtensions, + outputPrefix, outputSuffix, isLibtool, libtoolLinker); + } + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args) { + super.addImpliedArgs(debug, linkType, args); + if (getIdentifier().indexOf("mingw") >= 0) { + if (linkType.isSubsystemConsole()) { + args.addElement("-mconsole"); + } + if (linkType.isSubsystemGUI()) { + args.addElement("-mwindows"); + } + } + if (linkType.isStaticRuntime()) { + String[] cmdin = new String[]{GccCCompiler.CMD_PREFIX + "g++", + "-print-file-name=libstdc++.a"}; + String[] cmdout = CaptureStreamHandler.run(cmdin); + if (cmdout.length > 0) { + runtimeLibrary = cmdout[0]; + } else { + runtimeLibrary = null; + } + } else { + runtimeLibrary = "-lstdc++"; + } + } + public String[] addLibrarySets(CCTask task, LibrarySet[] libsets, + Vector preargs, Vector midargs, Vector endargs) { + String[] rs = super.addLibrarySets(task, libsets, preargs, midargs, + endargs); + if (runtimeLibrary != null) { + endargs.addElement(runtimeLibrary); + } + return rs; + } + /** + * Allows drived linker to decorate linker option. Override by GppLinker 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 + */ + public String decorateLinkerOption(StringBuffer buf, String arg) { + String decoratedArg = arg; + if (arg.length() > 1 && arg.charAt(0) == '-') { + switch (arg.charAt(1)) { + // + // passed automatically by GCC + // + case 'g' : + case 'f' : + case 'F' : + /* Darwin */ + case 'm' : + case 'O' : + case 'W' : + case 'l' : + case 'L' : + case 'u' : + break; + default : + boolean known = false; + for (int i = 0; i < linkerOptions.length; i++) { + if (linkerOptions[i].equals(arg)) { + known = true; + break; + } + } + if (!known) { + buf.setLength(0); + buf.append("-Wl,"); + buf.append(arg); + decoratedArg = buf.toString(); + } + break; + } + } + return decoratedArg; + } + /** + * Returns library path. + * + */ + public File[] getLibraryPath() { + if (libDirs == null) { + Vector dirs = new Vector(); + // Ask GCC where it will look for its libraries. + String[] args = new String[]{GccCCompiler.CMD_PREFIX + "g++", + "-print-search-dirs"}; + String[] cmdout = CaptureStreamHandler.run(args); + for (int i = 0; i < cmdout.length; ++i) { + int prefixIndex = cmdout[i].indexOf(libPrefix); + if (prefixIndex >= 0) { + // Special case DOS-type GCCs like MinGW or Cygwin + int s = prefixIndex + libPrefix.length(); + int t = cmdout[i].indexOf(';', s); + while (t > 0) { + dirs.addElement(cmdout[i].substring(s, t)); + s = t + 1; + t = cmdout[i].indexOf(';', s); + } + dirs.addElement(cmdout[i].substring(s)); + ++i; + for (; i < cmdout.length; ++i) { + dirs.addElement(cmdout[i]); + } + } + } + // Eliminate all but actual directories. + String[] libpath = new String[dirs.size()]; + dirs.copyInto(libpath); + int count = CUtil.checkDirectoryArray(libpath); + // Build return array. + libDirs = new File[count]; + int index = 0; + for (int i = 0; i < libpath.length; ++i) { + if (libpath[i] != null) { + libDirs[index++] = new File(libpath[i]); + } + } + } + return libDirs; + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return GccLibrarian.getInstance(); + } + if (type.isPluginModule()) { + if (GccProcessor.getMachine().indexOf("darwin") >= 0) { + return machPluginLinker; + } else { + return dllLinker; + } + } + if (type.isSharedLibrary()) { + if (GccProcessor.getMachine().indexOf("darwin") >= 0) { + return machDllLinker; + } else { + return dllLinker; + } + } + return instance; + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/LdLinker.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/LdLinker.java new file mode 100755 index 0000000..0cc5fbf --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/LdLinker.java @@ -0,0 +1,60 @@ +/* + * + * 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.gcc.cross.sparc_sun_solaris2; +import java.io.File; + +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.gcc.AbstractLdLinker; +/** + * Adapter for the 'ld' linker + * + * @author Curt Arnold + */ +public final class LdLinker extends AbstractLdLinker { + private static final String[] discardFiles = new String[0]; + private static final String[] libtoolObjFiles = new String[]{".fo", ".a", + ".lib", ".dll", ".so", ".sl"}; + private static final String[] objFiles = new String[]{".o", ".a", ".lib", + ".dll", ".so", ".sl"}; + private static final LdLinker dllLinker = new LdLinker( + GccCCompiler.CMD_PREFIX + "ld", objFiles, discardFiles, "lib", + ".so", false, new LdLinker(GccCCompiler.CMD_PREFIX + "ld", + objFiles, discardFiles, "lib", ".so", true, null)); + private static final LdLinker instance = new LdLinker( + GccCCompiler.CMD_PREFIX + "ld", objFiles, discardFiles, "", "", + false, null); + public static LdLinker getInstance() { + return instance; + } + private File[] libDirs; + private LdLinker(String command, String[] extensions, + String[] ignoredExtensions, String outputPrefix, + String outputSuffix, boolean isLibtool, LdLinker libtoolLinker) { + super(command, "-version", extensions, ignoredExtensions, outputPrefix, + outputSuffix, isLibtool, libtoolLinker); + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return GccLibrarian.getInstance(); + } + if (type.isSharedLibrary()) { + return dllLinker; + } + return instance; + } +} |