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
;
19 import java
.util
.Vector
;
21 import net
.sf
.antcontrib
.cpptasks
.CUtil
;
22 import net
.sf
.antcontrib
.cpptasks
.compiler
.LinkType
;
23 import net
.sf
.antcontrib
.cpptasks
.compiler
.Linker
;
24 import net
.sf
.antcontrib
.cpptasks
.compiler
.Processor
;
25 import net
.sf
.antcontrib
.cpptasks
.parser
.CParser
;
26 import net
.sf
.antcontrib
.cpptasks
.parser
.FortranParser
;
27 import net
.sf
.antcontrib
.cpptasks
.parser
.Parser
;
29 import org
.apache
.tools
.ant
.BuildException
;
30 import org
.apache
.tools
.ant
.types
.Environment
;
31 import net
.sf
.antcontrib
.cpptasks
.OptimizationEnum
;
34 * Adapter for the GCC C/C++ compiler
36 * @author Adam Murdoch
38 public final class GccCCompiler
extends GccCompatibleCCompiler
{
39 private final static String
[] sourceExtensions
= new String
[]{".c", /* C */
44 ".i", /* preprocessed C */
45 ".ii", /* preprocessed C++ */
48 ".m", /* Objective-C */
49 ".mm", /* Objected-C++ */
52 private final static String
[] headerExtensions
= new String
[]{".h", ".hpp",
54 private static final GccCCompiler cppInstance
= new GccCCompiler("c++",
55 sourceExtensions
, headerExtensions
, false,
56 new GccCCompiler("c++", sourceExtensions
, headerExtensions
, true,
57 null, false, null), false, null);
58 private static final GccCCompiler g77Instance
= new GccCCompiler("g77",
59 sourceExtensions
, headerExtensions
, false,
60 new GccCCompiler("g77", sourceExtensions
, headerExtensions
, true,
61 null, false, null), false, null);
62 private static final GccCCompiler gppInstance
= new GccCCompiler("g++",
63 sourceExtensions
, headerExtensions
, false,
64 new GccCCompiler("g++", sourceExtensions
, headerExtensions
, true,
65 null, false, null), false, null);
66 private static final GccCCompiler instance
= new GccCCompiler("gcc",
67 sourceExtensions
, headerExtensions
, false,
68 new GccCCompiler("gcc", sourceExtensions
, headerExtensions
, true,
69 null, false, null), false, null);
73 public static GccCCompiler
getCppInstance() {
79 public static GccCCompiler
getG77Instance() {
85 public static GccCCompiler
getGppInstance() {
91 public static GccCCompiler
getInstance() {
94 private String identifier
;
95 private File
[] includePath
;
96 private boolean isPICMeaningful
= true;
98 * Private constructor. Use GccCCompiler.getInstance() to get singleton
99 * instance of this class.
101 private GccCCompiler(String command
, String
[] sourceExtensions
,
102 String
[] headerExtensions
, boolean isLibtool
,
103 GccCCompiler libtoolCompiler
, boolean newEnvironment
,
105 super(command
, null, sourceExtensions
, headerExtensions
, isLibtool
,
106 libtoolCompiler
, newEnvironment
, env
);
107 isPICMeaningful
= System
.getProperty("os.name").indexOf("Windows") < 0;
109 public void addImpliedArgs(final Vector args
,
111 final boolean multithreaded
,
112 final boolean exceptions
,
113 final LinkType linkType
,
115 final OptimizationEnum optimization
,
116 final Boolean defaultflag
) {
117 super.addImpliedArgs(args
, debug
, multithreaded
,
118 exceptions
, linkType
, rtti
, optimization
, defaultflag
);
119 if (isPICMeaningful
&& linkType
.isSharedLibrary()) {
120 args
.addElement("-fPIC");
123 public Processor
changeEnvironment(boolean newEnvironment
, Environment env
) {
124 if (newEnvironment
|| env
!= null) {
125 return new GccCCompiler(getCommand(), this.getSourceExtensions(),
126 this.getHeaderExtensions(), this.getLibtool(),
127 (GccCCompiler
) this.getLibtoolCompiler(), newEnvironment
,
133 * Create parser to determine dependencies.
135 * Will create appropriate parser (C++, FORTRAN) based on file extension.
138 protected Parser
createParser(File source
) {
139 if (source
!= null) {
140 String sourceName
= source
.getName();
141 int lastDot
= sourceName
.lastIndexOf('.');
142 if (lastDot
>= 0 && lastDot
+ 1 < sourceName
.length()) {
143 char afterDot
= sourceName
.charAt(lastDot
+ 1);
144 if (afterDot
== 'f' || afterDot
== 'F') {
145 return new FortranParser();
149 return new CParser();
151 public File
[] getEnvironmentIncludePath() {
152 if (includePath
== null) {
154 // construct default include path from machine id and version id
156 String
[] defaultInclude
= new String
[1];
157 StringBuffer buf
= new StringBuffer("/lib/");
158 buf
.append(GccProcessor
.getMachine());
160 buf
.append(GccProcessor
.getVersion());
161 buf
.append("/include");
162 defaultInclude
[0] = buf
.toString();
164 // read specs file and look for -istart and -idirafter
166 String
[] specs
= GccProcessor
.getSpecs();
167 String
[][] optionValues
= GccProcessor
.parseSpecs(specs
, "*cpp:",
168 new String
[]{"-isystem ", "-idirafter "});
170 // if no entries were found, then use a default path
172 if (optionValues
[0].length
== 0 && optionValues
[1].length
== 0) {
173 optionValues
[0] = new String
[]{"/usr/local/include",
174 "/usr/include", "/usr/include/win32api"};
177 // remove mingw entries.
178 // For MinGW compiles this will mean the
179 // location of the sys includes will be
180 // wrong in dependencies.xml
181 // but that should have no significant effect
182 for (int i
= 0; i
< optionValues
.length
; i
++) {
183 for (int j
= 0; j
< optionValues
[i
].length
; j
++) {
184 if (optionValues
[i
][j
].indexOf("mingw") > 0) {
185 optionValues
[i
][j
] = null;
191 // we have to prepend location of gcc32
192 // and .. to start of absolute filenames to
193 // have something that will exist in the
194 // windows filesystem
195 if (GccProcessor
.isCygwin()) {
196 GccProcessor
.convertCygwinFilenames(optionValues
[0]);
197 GccProcessor
.convertCygwinFilenames(optionValues
[1]);
198 GccProcessor
.convertCygwinFilenames(defaultInclude
);
200 int count
= CUtil
.checkDirectoryArray(optionValues
[0]);
201 count
+= CUtil
.checkDirectoryArray(optionValues
[1]);
202 count
+= CUtil
.checkDirectoryArray(defaultInclude
);
203 includePath
= new File
[count
];
205 for (int i
= 0; i
< optionValues
.length
; i
++) {
206 for (int j
= 0; j
< optionValues
[i
].length
; j
++) {
207 if (optionValues
[i
][j
] != null) {
208 includePath
[index
++] = new File(optionValues
[i
][j
]);
212 for (int i
= 0; i
< defaultInclude
.length
; i
++) {
213 if (defaultInclude
[i
] != null) {
214 includePath
[index
++] = new File(defaultInclude
[i
]);
218 return (File
[]) includePath
.clone();
220 public String
getIdentifier() throws BuildException
{
221 if (identifier
== null) {
224 buf
= new StringBuffer("libtool ");
226 buf
= new StringBuffer(' ');
228 buf
.append(getCommand());
230 buf
.append(GccProcessor
.getVersion());
232 buf
.append(GccProcessor
.getMachine());
233 identifier
= buf
.toString();
237 public Linker
getLinker(LinkType linkType
) {
238 return GccLinker
.getInstance().getLinker(linkType
);
240 public int getMaximumCommandLength() {
241 return Integer
.MAX_VALUE
;