3 * Copyright 2002-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
.compiler
;
18 import java
.io
.BufferedReader
;
20 import java
.io
.FileReader
;
21 import java
.io
.IOException
;
22 import java
.io
.Reader
;
23 import java
.util
.Vector
;
24 import net
.sf
.antcontrib
.cpptasks
.CCTask
;
25 import net
.sf
.antcontrib
.cpptasks
.CUtil
;
26 import net
.sf
.antcontrib
.cpptasks
.CompilerDef
;
27 import net
.sf
.antcontrib
.cpptasks
.DependencyInfo
;
28 import net
.sf
.antcontrib
.cpptasks
.ProcessorDef
;
29 import net
.sf
.antcontrib
.cpptasks
.parser
.Parser
;
30 import net
.sf
.antcontrib
.cpptasks
.TargetDef
;
33 * An abstract compiler implementation.
35 * @author Adam Murdoch
38 public abstract class AbstractCompiler
extends AbstractProcessor
41 private static final String
[] emptyIncludeArray
= new String
[0];
42 private String outputSuffix
;
43 protected AbstractCompiler(String
[] sourceExtensions
,
44 String
[] headerExtensions
, String outputSuffix
) {
45 super(sourceExtensions
, headerExtensions
);
46 this.outputSuffix
= outputSuffix
;
49 * Checks file name to see if parse should be attempted
51 * Default implementation returns false for files with extensions '.dll',
55 protected boolean canParse(File sourceFile
) {
56 String sourceName
= sourceFile
.toString();
57 int lastPeriod
= sourceName
.lastIndexOf('.');
58 if (lastPeriod
>= 0 && lastPeriod
== sourceName
.length() - 4) {
59 String ext
= sourceName
.substring(lastPeriod
).toUpperCase();
60 if (ext
.equals(".DLL") || ext
.equals(".TLB") || ext
.equals(".RES")) {
66 abstract protected CompilerConfiguration
createConfiguration(CCTask task
,
67 LinkType linkType
, ProcessorDef
[] baseConfigs
,
68 CompilerDef specificConfig
, TargetDef targetPlatform
);
69 public ProcessorConfiguration
createConfiguration(CCTask task
,
70 LinkType linkType
, ProcessorDef
[] baseConfigs
,
71 ProcessorDef specificConfig
, TargetDef targetPlatform
) {
72 if (specificConfig
== null) {
73 throw new NullPointerException("specificConfig");
75 return createConfiguration(task
, linkType
, baseConfigs
,
76 (CompilerDef
) specificConfig
, targetPlatform
);
78 abstract protected Parser
createParser(File sourceFile
);
79 protected String
getBaseOutputName(String inputFile
) {
80 int lastSlash
= inputFile
.lastIndexOf('/');
81 int lastReverse
= inputFile
.lastIndexOf('\\');
82 int lastSep
= inputFile
.lastIndexOf(File
.separatorChar
);
83 if (lastReverse
> lastSlash
) {
84 lastSlash
= lastReverse
;
86 if (lastSep
> lastSlash
) {
89 int lastPeriod
= inputFile
.lastIndexOf('.');
91 lastPeriod
= inputFile
.length();
93 return inputFile
.substring(lastSlash
+ 1, lastPeriod
);
95 public String
getOutputFileName(String inputFile
) {
97 // if a recognized input file
99 if (bid(inputFile
) > 1) {
100 String baseName
= getBaseOutputName(inputFile
);
101 return baseName
+ outputSuffix
;
106 * Returns dependency info for the specified source file
109 * task for any diagnostic output
113 * include path to be used to resolve included files
115 * @param sysIncludePath
116 * sysinclude path from build file, files resolved using
117 * sysInclude path will not participate in dependency analysis
119 * @param envIncludePath
120 * include path from environment variable, files resolved with
121 * envIncludePath will not participate in dependency analysis
124 * used to produce relative paths in DependencyInfo
125 * @param includePathIdentifier
126 * used to distinguish DependencyInfo's from different include
129 * @author Curt Arnold
131 public final DependencyInfo
parseIncludes(CCTask task
, File source
,
132 File
[] includePath
, File
[] sysIncludePath
, File
[] envIncludePath
,
133 File baseDir
, String includePathIdentifier
) {
135 // if any of the include files can not be identified
136 // change the sourceLastModified to Long.MAX_VALUE to
137 // force recompilation of anything that depends on it
138 long sourceLastModified
= source
.lastModified();
139 File
[] sourcePath
= new File
[1];
140 sourcePath
[0] = new File(source
.getParent());
141 Vector onIncludePath
= new Vector();
142 Vector onSysIncludePath
= new Vector();
145 baseDirPath
= baseDir
.getCanonicalPath();
146 } catch (IOException ex
) {
147 baseDirPath
= baseDir
.toString();
149 String relativeSource
= CUtil
.getRelativePath(baseDirPath
, source
);
150 String
[] includes
= emptyIncludeArray
;
151 if (canParse(source
)) {
152 Parser parser
= createParser(source
);
154 Reader reader
= new BufferedReader(new FileReader(source
));
155 parser
.parse(reader
);
156 includes
= parser
.getIncludes();
157 } catch (IOException ex
) {
158 task
.log("Error parsing " + source
.toString() + ":"
160 includes
= new String
[0];
163 for (int i
= 0; i
< includes
.length
; i
++) {
164 String includeName
= includes
[i
];
165 if (!resolveInclude(includeName
, sourcePath
, onIncludePath
)) {
166 if (!resolveInclude(includeName
, includePath
, onIncludePath
)) {
167 if (!resolveInclude(includeName
, sysIncludePath
,
169 if (!resolveInclude(includeName
, envIncludePath
,
172 // this should be enough to require us to reparse
173 // the file with the missing include for dependency
174 // information without forcing a rebuild
175 sourceLastModified
++;
181 for (int i
= 0; i
< onIncludePath
.size(); i
++) {
182 String relativeInclude
= CUtil
.getRelativePath(baseDirPath
,
183 (File
) onIncludePath
.elementAt(i
));
184 onIncludePath
.setElementAt(relativeInclude
, i
);
186 for (int i
= 0; i
< onSysIncludePath
.size(); i
++) {
187 String relativeInclude
= CUtil
.getRelativePath(baseDirPath
,
188 (File
) onSysIncludePath
.elementAt(i
));
189 onSysIncludePath
.setElementAt(relativeInclude
, i
);
191 return new DependencyInfo(includePathIdentifier
, relativeSource
,
192 sourceLastModified
, onIncludePath
, onSysIncludePath
);
194 protected boolean resolveInclude(String includeName
, File
[] includePath
,
196 for (int i
= 0; i
< includePath
.length
; i
++) {
197 File includeFile
= new File(includePath
[i
], includeName
);
198 if (includeFile
.exists()) {
199 onThisPath
.addElement(includeFile
);