/* * #%L * Native ARchive plugin for Maven * %% * Copyright (C) 2002 - 2014 NAR Maven Plugin developers. * %% * 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. * #L% */ package com.github.maven_nar.cpptasks.gcc; import java.io.File; import java.util.Vector; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.types.Environment; import com.github.maven_nar.cpptasks.CUtil; import com.github.maven_nar.cpptasks.OptimizationEnum; import com.github.maven_nar.cpptasks.compiler.LinkType; import com.github.maven_nar.cpptasks.compiler.Linker; import com.github.maven_nar.cpptasks.compiler.Processor; import com.github.maven_nar.cpptasks.parser.CParser; import com.github.maven_nar.cpptasks.parser.FortranParser; import com.github.maven_nar.cpptasks.parser.Parser; /** * 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 */ ".f90", /* FORTRAN 90 */ ".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); // FREEHEP private static final GccCCompiler gfortranInstance = new GccCCompiler("gfortran", sourceExtensions, headerExtensions, false, new GccCCompiler("gfortran", 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); private static final GccCCompiler clangInstance = new GccCCompiler("clang", sourceExtensions, headerExtensions, false, new GccCCompiler("clang", sourceExtensions, headerExtensions, true, null, false, null), false, null); private static final GccCCompiler cpplangInstance = new GccCCompiler("clang++", sourceExtensions, headerExtensions, false, new GccCCompiler("clang++", sourceExtensions, headerExtensions, true, null, false, null), false, null); /** * Gets clang adapter */ public static GccCCompiler getCLangInstance() { return clangInstance; } /** * Gets clang++ adapter */ public static GccCCompiler getCLangppInstance() { return cpplangInstance; } /** * Gets c++ adapter */ public static GccCCompiler getCppInstance() { return cppInstance; } /** * Gets g77 adapter */ public static GccCCompiler getG77Instance() { return g77Instance; } /** * Gets g77 adapter */ // FREEHEPBEGIN public static GccCCompiler getGFortranInstance() { return gfortranInstance; } // FREEHEPEND /** * 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(final String command, final String[] sourceExtensions, final String[] headerExtensions, final boolean isLibtool, final GccCCompiler libtoolCompiler, final boolean newEnvironment, final Environment env) { super(command, null, sourceExtensions, headerExtensions, isLibtool, libtoolCompiler, newEnvironment, env); this.isPICMeaningful = !System.getProperty("os.name").contains("Windows"); } @Override 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 (this.isPICMeaningful && linkType.isSharedLibrary()) { args.addElement("-fPIC"); } // BEGINFREEHEP // Add -fno_rtti only for g++ and c++ if (!getCommand().equals("g77") && !getCommand().equals("gcc") && rtti != null && !rtti.booleanValue()) { // Darren Sargent: fix RTTI option args.addElement("-fno-rtti"); } // ENDFREEHEP } @Override public Processor changeEnvironment(final boolean newEnvironment, final 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. * */ @Override protected Parser createParser(final File source) { if (source != null) { final String sourceName = source.getName(); final int lastDot = sourceName.lastIndexOf('.'); if (lastDot >= 0 && lastDot + 1 < sourceName.length()) { final char afterDot = sourceName.charAt(lastDot + 1); if (afterDot == 'f' || afterDot == 'F') { return new FortranParser(); } } } return new CParser(); } @Override public File[] getEnvironmentIncludePath() { if (this.includePath == null) { // // construct default include path from machine id and version id // final String[] defaultInclude = new String[1]; final String buf = "/lib/" + GccProcessor.getMachine() + '/' + GccProcessor.getVersion() + "/include"; defaultInclude[0] = buf; // // read specs file and look for -istart and -idirafter // final String[] specs = GccProcessor.getSpecs(); final 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); this.includePath = new File[count]; int index = 0; for (final String[] optionValue : optionValues) { for (final String anOptionValue : optionValue) { if (anOptionValue != null) { this.includePath[index++] = new File(anOptionValue); } } } for (final String element : defaultInclude) { if (element != null) { this.includePath[index++] = new File(element); } } } return this.includePath.clone(); } @Override public String getIdentifier() throws BuildException { if (this.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()); this.identifier = buf.toString(); } return this.identifier; } @Override public Linker getLinker(final LinkType linkType) { return GccLinker.getInstance().getLinker(linkType); } // BEGINFREEHEP @Override public int getMaximumCommandLength() { return isWindows() ? 20000 : Integer.MAX_VALUE; } // ENDFREEHEP }