3 * Copyright 2001-2004 The Ant-Contrib project
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 package net
.sf
.antcontrib
.cpptasks
.gcc
.cross
;
19 import java
.util
.Vector
;
20 import net
.sf
.antcontrib
.cpptasks
.CCTask
;
21 import net
.sf
.antcontrib
.cpptasks
.CUtil
;
22 import net
.sf
.antcontrib
.cpptasks
.CompilerParam
;
23 import net
.sf
.antcontrib
.cpptasks
.compiler
.CommandLineCompilerConfiguration
;
24 import net
.sf
.antcontrib
.cpptasks
.compiler
.LinkType
;
25 import net
.sf
.antcontrib
.cpptasks
.compiler
.Linker
;
26 import net
.sf
.antcontrib
.cpptasks
.compiler
.Processor
;
27 import net
.sf
.antcontrib
.cpptasks
.compiler
.ProgressMonitor
;
28 import net
.sf
.antcontrib
.cpptasks
.gcc
.GccCompatibleCCompiler
;
29 import net
.sf
.antcontrib
.cpptasks
.parser
.CParser
;
30 import net
.sf
.antcontrib
.cpptasks
.parser
.FortranParser
;
31 import net
.sf
.antcontrib
.cpptasks
.parser
.Parser
;
32 import org
.apache
.tools
.ant
.BuildException
;
33 import org
.apache
.tools
.ant
.types
.Environment
;
34 import net
.sf
.antcontrib
.cpptasks
.OptimizationEnum
;
37 * Adapter for the GCC C/C++ compiler
39 * @author Adam Murdoch
41 public final class GccCCompiler
extends GccCompatibleCCompiler
{
42 private final static String
[] headerExtensions
= new String
[]{".h", ".hpp",
44 private final static String
[] sourceExtensions
= new String
[]{".c", /* C */
49 ".i", /* preprocessed C */
50 ".ii", /* preprocessed C++ */
53 ".m", /* Objective-C */
54 ".mm", /* Objected-C++ */
57 private static final GccCCompiler cppInstance
= new GccCCompiler("c++",
58 sourceExtensions
, headerExtensions
, false,
59 new GccCCompiler("c++", sourceExtensions
, headerExtensions
, true,
60 null, false, null), false, null);
61 private static final GccCCompiler g77Instance
= new GccCCompiler("g77",
62 sourceExtensions
, headerExtensions
, false,
63 new GccCCompiler("g77", sourceExtensions
, headerExtensions
, true,
64 null, false, null), false, null);
65 private static final GccCCompiler gppInstance
= new GccCCompiler("g++",
66 sourceExtensions
, headerExtensions
, false,
67 new GccCCompiler("g++", sourceExtensions
, headerExtensions
, true,
68 null, false, null), false, null);
69 private static final GccCCompiler instance
= new GccCCompiler("gcc",
70 sourceExtensions
, headerExtensions
, false,
71 new GccCCompiler("gcc", sourceExtensions
, headerExtensions
, true,
72 null, false, null), false, null);
76 public static GccCCompiler
getCppInstance() {
82 public static GccCCompiler
getG77Instance() {
88 public static GccCCompiler
getGppInstance() {
94 public static GccCCompiler
getInstance() {
97 private String identifier
;
98 private File
[] includePath
;
99 private boolean isPICMeaningful
= true;
101 * Private constructor. Use GccCCompiler.getInstance() to get singleton
102 * instance of this class.
104 private GccCCompiler(String command
, String
[] sourceExtensions
,
105 String
[] headerExtensions
, boolean isLibtool
,
106 GccCCompiler libtoolCompiler
, boolean newEnvironment
,
108 super(command
, null, sourceExtensions
, headerExtensions
, isLibtool
,
109 libtoolCompiler
, newEnvironment
, env
);
110 isPICMeaningful
= System
.getProperty("os.name").indexOf("Windows") < 0;
112 public void addImpliedArgs(final Vector args
,
114 final boolean multithreaded
,
115 final boolean exceptions
,
116 final LinkType linkType
,
118 final OptimizationEnum optimization
,
119 final Boolean defaultflag
) {
120 super.addImpliedArgs(args
, debug
, multithreaded
,
121 exceptions
, linkType
, rtti
, optimization
, defaultflag
);
122 if (isPICMeaningful
&& linkType
.isSharedLibrary()) {
123 args
.addElement("-fPIC");
126 public Processor
changeEnvironment(boolean newEnvironment
, Environment env
) {
127 if (newEnvironment
|| env
!= null) {
128 return new GccCCompiler(getCommand(), this.getSourceExtensions(),
129 this.getHeaderExtensions(), this.getLibtool(),
130 (GccCCompiler
) this.getLibtoolCompiler(), newEnvironment
,
135 protected Object
clone() throws CloneNotSupportedException
{
136 GccCCompiler clone
= (GccCCompiler
) super.clone();
139 public void compile(CCTask task
, File outputDir
, String
[] sourceFiles
,
140 String
[] args
, String
[] endArgs
, boolean relentless
,
141 CommandLineCompilerConfiguration config
, ProgressMonitor monitor
)
142 throws BuildException
{
144 GccCCompiler clone
= (GccCCompiler
) this.clone();
145 CompilerParam param
= config
.getParam("target");
147 clone
.setCommand(param
.getValue() + "-" + this.getCommand());
148 clone
.supercompile(task
, outputDir
, sourceFiles
, args
, endArgs
,
149 relentless
, config
, monitor
);
150 } catch (CloneNotSupportedException e
) {
151 supercompile(task
, outputDir
, sourceFiles
, args
, endArgs
,
152 relentless
, config
, monitor
);
156 * Create parser to determine dependencies.
158 * Will create appropriate parser (C++, FORTRAN) based on file extension.
161 protected Parser
createParser(File source
) {
162 if (source
!= null) {
163 String sourceName
= source
.getName();
164 int lastDot
= sourceName
.lastIndexOf('.');
165 if (lastDot
>= 0 && lastDot
+ 1 < sourceName
.length()) {
166 char afterDot
= sourceName
.charAt(lastDot
+ 1);
167 if (afterDot
== 'f' || afterDot
== 'F') {
168 return new FortranParser();
172 return new CParser();
174 public File
[] getEnvironmentIncludePath() {
175 if (includePath
== null) {
177 // construct default include path from machine id and version id
179 String
[] defaultInclude
= new String
[1];
180 StringBuffer buf
= new StringBuffer("/lib/");
181 buf
.append(GccProcessor
.getMachine());
183 buf
.append(GccProcessor
.getVersion());
184 buf
.append("/include");
185 defaultInclude
[0] = buf
.toString();
187 // read specs file and look for -istart and -idirafter
189 String
[] specs
= GccProcessor
.getSpecs();
190 String
[][] optionValues
= GccProcessor
.parseSpecs(specs
, "*cpp:",
191 new String
[]{"-isystem ", "-idirafter "});
193 // if no entries were found, then use a default path
195 if (optionValues
[0].length
== 0 && optionValues
[1].length
== 0) {
196 optionValues
[0] = new String
[]{"/usr/local/include",
197 "/usr/include", "/usr/include/win32api"};
200 // remove mingw entries.
201 // For MinGW compiles this will mean the
202 // location of the sys includes will be
203 // wrong in dependencies.xml
204 // but that should have no significant effect
205 for (int i
= 0; i
< optionValues
.length
; i
++) {
206 for (int j
= 0; j
< optionValues
[i
].length
; j
++) {
207 if (optionValues
[i
][j
].indexOf("mingw") > 0) {
208 optionValues
[i
][j
] = null;
214 // we have to prepend location of gcc32
215 // and .. to start of absolute filenames to
216 // have something that will exist in the
217 // windows filesystem
218 if (GccProcessor
.isCygwin()) {
219 GccProcessor
.convertCygwinFilenames(optionValues
[0]);
220 GccProcessor
.convertCygwinFilenames(optionValues
[1]);
221 GccProcessor
.convertCygwinFilenames(defaultInclude
);
223 int count
= CUtil
.checkDirectoryArray(optionValues
[0]);
224 count
+= CUtil
.checkDirectoryArray(optionValues
[1]);
225 count
+= CUtil
.checkDirectoryArray(defaultInclude
);
226 includePath
= new File
[count
];
228 for (int i
= 0; i
< optionValues
.length
; i
++) {
229 for (int j
= 0; j
< optionValues
[i
].length
; j
++) {
230 if (optionValues
[i
][j
] != null) {
231 includePath
[index
++] = new File(optionValues
[i
][j
]);
235 for (int i
= 0; i
< defaultInclude
.length
; i
++) {
236 if (defaultInclude
[i
] != null) {
237 includePath
[index
++] = new File(defaultInclude
[i
]);
241 return (File
[]) includePath
.clone();
243 public String
getIdentifier() throws BuildException
{
244 if (identifier
== null) {
247 buf
= new StringBuffer("libtool ");
249 buf
= new StringBuffer(' ');
251 buf
.append(getCommand());
253 buf
.append(GccProcessor
.getVersion());
255 buf
.append(GccProcessor
.getMachine());
256 identifier
= buf
.toString();
260 public Linker
getLinker(LinkType linkType
) {
261 return GccLinker
.getInstance().getLinker(linkType
);
263 public int getMaximumCommandLength() {
264 return Integer
.MAX_VALUE
;
266 private void supercompile(CCTask task
, File outputDir
,
267 String
[] sourceFiles
, String
[] args
, String
[] endArgs
,
268 boolean relentless
, CommandLineCompilerConfiguration config
,
269 ProgressMonitor monitor
) throws BuildException
{
270 super.compile(task
, outputDir
, sourceFiles
, args
, endArgs
, relentless
,