View Javadoc

1   /*
2    * #%L
3    * Native ARchive plugin for Maven
4    * %%
5    * Copyright (C) 2002 - 2014 NAR Maven Plugin developers.
6    * %%
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   * 
11   * http://www.apache.org/licenses/LICENSE-2.0
12   * 
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * #L%
19   */
20  package com.github.maven_nar.cpptasks.gcc;
21  
22  import java.io.File;
23  import java.util.Vector;
24  
25  import org.apache.tools.ant.BuildException;
26  import org.apache.tools.ant.types.Environment;
27  
28  import com.github.maven_nar.cpptasks.CUtil;
29  import com.github.maven_nar.cpptasks.OptimizationEnum;
30  import com.github.maven_nar.cpptasks.compiler.LinkType;
31  import com.github.maven_nar.cpptasks.compiler.Linker;
32  import com.github.maven_nar.cpptasks.compiler.Processor;
33  import com.github.maven_nar.cpptasks.parser.CParser;
34  import com.github.maven_nar.cpptasks.parser.FortranParser;
35  import com.github.maven_nar.cpptasks.parser.Parser;
36  
37  /**
38   * Adapter for the GCC C/C++ compiler
39   *
40   * @author Adam Murdoch
41   */
42  public final class GccCCompiler extends GccCompatibleCCompiler {
43    private final static String[] sourceExtensions = new String[] {
44        ".c", /* C */
45        ".cc", /* C++ */
46        ".cpp", /* C++ */
47        ".cxx", /* C++ */
48        ".c++", /* C++ */
49        ".i", /* preprocessed C */
50        ".ii", /* preprocessed C++ */
51        ".f", /* FORTRAN */
52        ".for", /* FORTRAN */
53        ".f90", /* FORTRAN 90 */
54        ".m", /* Objective-C */
55        ".mm", /* Objected-C++ */
56        ".s" /* Assembly */
57    };
58    private final static String[] headerExtensions = new String[] {
59        ".h", ".hpp", ".inl"
60    };
61    private static final GccCCompiler cppInstance = new GccCCompiler("c++", sourceExtensions, headerExtensions, false,
62        new GccCCompiler("c++", sourceExtensions, headerExtensions, true, null, false, null), false, null);
63    private static final GccCCompiler g77Instance = new GccCCompiler("g77", sourceExtensions, headerExtensions, false,
64        new GccCCompiler("g77", sourceExtensions, headerExtensions, true, null, false, null), false, null);
65    // FREEHEP
66    private static final GccCCompiler gfortranInstance = new GccCCompiler("gfortran", sourceExtensions, headerExtensions,
67        false, new GccCCompiler("gfortran", sourceExtensions, headerExtensions, true, null, false, null), false, null);
68    private static final GccCCompiler gppInstance = new GccCCompiler("g++", sourceExtensions, headerExtensions, false,
69        new GccCCompiler("g++", sourceExtensions, headerExtensions, true, null, false, null), false, null);
70    private static final GccCCompiler instance = new GccCCompiler("gcc", sourceExtensions, headerExtensions, false,
71        new GccCCompiler("gcc", sourceExtensions, headerExtensions, true, null, false, null), false, null);
72    private static final GccCCompiler clangInstance = new GccCCompiler("clang", sourceExtensions, headerExtensions,
73        false, new GccCCompiler("clang", sourceExtensions, headerExtensions, true, null, false, null), false, null);
74    private static final GccCCompiler cpplangInstance = new GccCCompiler("clang++", sourceExtensions, headerExtensions,
75        false, new GccCCompiler("clang++", sourceExtensions, headerExtensions, true, null, false, null), false, null);
76  
77    /**
78     * Gets clang adapter
79     */
80    public static GccCCompiler getCLangInstance() {
81      return clangInstance;
82    }
83  
84    /**
85     * Gets clang++ adapter
86     */
87    public static GccCCompiler getCLangppInstance() {
88      return cpplangInstance;
89    }
90  
91    /**
92     * Gets c++ adapter
93     */
94    public static GccCCompiler getCppInstance() {
95      return cppInstance;
96    }
97  
98    /**
99     * Gets g77 adapter
100    */
101   public static GccCCompiler getG77Instance() {
102     return g77Instance;
103   }
104 
105   /**
106    * Gets g77 adapter
107    */
108   // FREEHEPBEGIN
109   public static GccCCompiler getGFortranInstance() {
110     return gfortranInstance;
111   }
112 
113   // FREEHEPEND
114   /**
115    * Gets gpp adapter
116    */
117   public static GccCCompiler getGppInstance() {
118     return gppInstance;
119   }
120 
121   /**
122    * Gets gcc adapter
123    */
124   public static GccCCompiler getInstance() {
125     return instance;
126   }
127 
128   private String identifier;
129   private File[] includePath;
130   private boolean isPICMeaningful = true;
131 
132   /**
133    * Private constructor. Use GccCCompiler.getInstance() to get singleton
134    * instance of this class.
135    */
136   private GccCCompiler(final String command, final String[] sourceExtensions, final String[] headerExtensions,
137       final boolean isLibtool, final GccCCompiler libtoolCompiler, final boolean newEnvironment, final Environment env) {
138     super(command, null, sourceExtensions, headerExtensions, isLibtool, libtoolCompiler, newEnvironment, env);
139     this.isPICMeaningful = !System.getProperty("os.name").contains("Windows");
140   }
141 
142   @Override
143   public void addImpliedArgs(final Vector args, final boolean debug, final boolean multithreaded,
144       final boolean exceptions, final LinkType linkType, final Boolean rtti, final OptimizationEnum optimization) {
145     super.addImpliedArgs(args, debug, multithreaded, exceptions, linkType, rtti, optimization);
146     if (this.isPICMeaningful && linkType.isSharedLibrary()) {
147       args.addElement("-fPIC");
148     }
149     // BEGINFREEHEP
150     // Add -fno_rtti only for g++ and c++
151     if (!getCommand().equals("g77") && !getCommand().equals("gcc") && rtti != null && !rtti.booleanValue()) {
152       // Darren Sargent: fix RTTI option
153       args.addElement("-fno-rtti");
154     }
155     // ENDFREEHEP
156   }
157 
158   @Override
159   public Processor changeEnvironment(final boolean newEnvironment, final Environment env) {
160     if (newEnvironment || env != null) {
161       return new GccCCompiler(getCommand(), this.getSourceExtensions(), this.getHeaderExtensions(), this.getLibtool(),
162           (GccCCompiler) this.getLibtoolCompiler(), newEnvironment, env);
163     }
164     return this;
165   }
166 
167   /**
168    * Create parser to determine dependencies.
169    * 
170    * Will create appropriate parser (C++, FORTRAN) based on file extension.
171    * 
172    */
173   @Override
174   protected Parser createParser(final File source) {
175     if (source != null) {
176       final String sourceName = source.getName();
177       final int lastDot = sourceName.lastIndexOf('.');
178       if (lastDot >= 0 && lastDot + 1 < sourceName.length()) {
179         final char afterDot = sourceName.charAt(lastDot + 1);
180         if (afterDot == 'f' || afterDot == 'F') {
181           return new FortranParser();
182         }
183       }
184     }
185     return new CParser();
186   }
187 
188   @Override
189   public File[] getEnvironmentIncludePath() {
190     if (this.includePath == null) {
191       //
192       // construct default include path from machine id and version id
193       //
194       final String[] defaultInclude = new String[1];
195       final String buf = "/lib/" + GccProcessor.getMachine() +
196           '/' +
197           GccProcessor.getVersion() +
198           "/include";
199       defaultInclude[0] = buf;
200       //
201       // read specs file and look for -istart and -idirafter
202       //
203       final String[] specs = GccProcessor.getSpecs();
204       final String[][] optionValues = GccProcessor.parseSpecs(specs, "*cpp:", new String[] {
205           "-isystem ", "-idirafter "
206       });
207       //
208       // if no entries were found, then use a default path
209       //
210       if (optionValues[0].length == 0 && optionValues[1].length == 0) {
211         optionValues[0] = new String[] {
212             "/usr/local/include", "/usr/include", "/usr/include/win32api"
213         };
214       }
215       //
216       // remove mingw entries.
217       // For MinGW compiles this will mean the
218       // location of the sys includes will be
219       // wrong in dependencies.xml
220       // but that should have no significant effect
221       for (int i = 0; i < optionValues.length; i++) {
222         for (int j = 0; j < optionValues[i].length; j++) {
223           if (optionValues[i][j].indexOf("mingw") > 0) {
224             optionValues[i][j] = null;
225           }
226         }
227       }
228       //
229       // if cygwin then
230       // we have to prepend location of gcc32
231       // and .. to start of absolute filenames to
232       // have something that will exist in the
233       // windows filesystem
234       if (GccProcessor.isCygwin()) {
235         GccProcessor.convertCygwinFilenames(optionValues[0]);
236         GccProcessor.convertCygwinFilenames(optionValues[1]);
237         GccProcessor.convertCygwinFilenames(defaultInclude);
238       }
239       int count = CUtil.checkDirectoryArray(optionValues[0]);
240       count += CUtil.checkDirectoryArray(optionValues[1]);
241       count += CUtil.checkDirectoryArray(defaultInclude);
242       this.includePath = new File[count];
243       int index = 0;
244       for (final String[] optionValue : optionValues) {
245         for (final String anOptionValue : optionValue) {
246           if (anOptionValue != null) {
247             this.includePath[index++] = new File(anOptionValue);
248           }
249         }
250       }
251       for (final String element : defaultInclude) {
252         if (element != null) {
253           this.includePath[index++] = new File(element);
254         }
255       }
256     }
257     return this.includePath.clone();
258   }
259 
260   @Override
261   public String getIdentifier() throws BuildException {
262     if (this.identifier == null) {
263       StringBuffer buf;
264       if (getLibtool()) {
265         buf = new StringBuffer("libtool ");
266       } else {
267         buf = new StringBuffer(" ");
268       }
269       buf.append(getCommand());
270       buf.append(' ');
271       buf.append(GccProcessor.getVersion());
272       buf.append(' ');
273       buf.append(GccProcessor.getMachine());
274       this.identifier = buf.toString();
275     }
276     return this.identifier;
277   }
278 
279   @Override
280   public Linker getLinker(final LinkType linkType) {
281     return GccLinker.getInstance().getLinker(linkType);
282   }
283 
284   // BEGINFREEHEP
285   @Override
286   public int getMaximumCommandLength() {
287     return isWindows() ? 20000 : Integer.MAX_VALUE;
288   }
289   // ENDFREEHEP
290 }