001: /*
002: * Copyright 1999-2004 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.jk.ant.compilers;
018:
019: import java.io.File;
020: import java.util.Enumeration;
021: import java.util.Vector;
022:
023: import org.apache.jk.ant.Def;
024: import org.apache.jk.ant.SoTask;
025: import org.apache.jk.ant.Source;
026: import org.apache.tools.ant.BuildException;
027: import org.apache.tools.ant.types.Commandline;
028:
029: /* Modeled after javac
030: */
031:
032: /**
033: * s/javac/C compiler/
034: *
035: * The interface that all compiler adapters must adher to.
036: *
037: * <p>A compiler adapter is an adapter that interprets the javac's
038: * parameters in preperation to be passed off to the compier this
039: * adapter represents. As all the necessary values are stored in the
040: * Javac task itself, the only thing all adapters need is the javac
041: * task, the execute command and a parameterless constructor (for
042: * reflection).</p>
043: *
044: * @author Jay Dickon Glanville <a href="mailto:jayglanville@home.com">jayglanville@home.com</a>
045: * @author Costin Manolache
046: */
047: public abstract class CompilerAdapter extends SoTask {
048: SoTask so;
049: Vector compileList;
050:
051: public CompilerAdapter() {
052: so = this ;
053: };
054:
055: public void setSoTask(SoTask so) {
056: this .so = so;
057: so.duplicateTo(this );
058: }
059:
060: // /** @deprecated
061: // */
062: // public GlobPatternMapper getOMapper() {
063: // return null;
064: // }
065:
066: /** Return the files that depend on a src file.
067: * The first item should be the .o file used for linking.
068: */
069: public abstract String[] getTargetFiles(Source src);
070:
071: public void execute() throws BuildException {
072: super .findSourceFiles();
073: Vector compileList = findCompileList(srcList);
074: compile(compileList);
075: }
076:
077: /** Verify if a .c file needs compilation.
078: * As with javac, we assume a fixed build structure, where all .o
079: * files are in a separate directory from the sources ( no mess ).
080: *
081: * XXX Hack makedepend somehow into this.
082: */
083: public boolean needCompile(Source source) {
084: // For each .c file we'll have a .o file in the build dir,
085: // with the same name.
086: File srcF = source.getFile();
087: if (!srcF.exists()) {
088: if (debug > 0)
089: log("No source file " + srcF);
090: return false;
091: }
092:
093: String targetNames[] = getTargetFiles(source);
094: if (targetNames == null || targetNames.length == 0) {
095: if (debug > 0)
096: log("No target files " + srcF);
097: return true; // strange, probably different extension ?
098: }
099: String targetName = targetNames[0];
100:
101: String targetDir = source.getPackage();
102: File f1 = new File(buildDir, targetDir);
103: File target = new File(f1, targetName);
104: // System.out.println("XXX " + target );
105: if (!target.exists()) {
106: if (debug > 0)
107: log("Target doesn't exist " + target);
108: return true;
109: }
110: if (oldestO > target.lastModified()) {
111: oldestO = target.lastModified();
112: oldestOFile = target;
113: }
114: if (srcF.lastModified() > target.lastModified())
115: return true;
116:
117: if (debug > 0)
118: log("No need to compile " + srcF + " target " + target);
119: return false;
120: }
121:
122: /** Remove all generated files, cleanup
123: */
124: public void removeOFiles(Vector srcList) {
125: for (int i = 0; i < srcList.size(); i++) {
126: // log( "Checking " + (Source)srcList.elementAt(i));
127: Source source = (Source) srcList.elementAt(i);
128: String targetNA[] = getTargetFiles(source);
129: if (targetNA == null)
130: continue;
131: String targetDir = source.getPackage();
132: File f1 = new File(buildDir, targetDir);
133: for (int j = 0; j < targetNA.length; j++) {
134: File target = new File(f1, targetNA[j]);
135: // Check the dependency
136: if (target.exists()) {
137: // Remove it - we'll do a full build
138: target.delete();
139: log("Removing " + target);
140: }
141: }
142: }
143: }
144:
145: // XXX modified as side-effect of checking files with needCompile()
146: long oldestO = System.currentTimeMillis();
147: File oldestOFile = null;
148:
149: /** Find the subset of the source list that needs compilation.
150: */
151: protected Vector findCompileList(Vector srcList)
152: throws BuildException {
153: Vector compileList = new Vector();
154:
155: for (int i = 0; i < srcList.size(); i++) {
156: Source source = (Source) srcList.elementAt(i);
157: File srcFile = source.getFile();
158:
159: if (!srcFile.exists()) {
160: throw new BuildException("Source \""
161: + srcFile.getPath() + "\" does not exist!",
162: location);
163: }
164:
165: // Check the dependency
166: if (needCompile(source))
167: compileList.addElement(source);
168: }
169:
170: if (checkDepend(oldestO, oldestOFile)) {
171: log("Dependency expired, removing " + srcList.size()
172: + " .o files and doing a full build ");
173: removeOFiles(srcList);
174: compileList = new Vector();
175: for (int i = 0; i < srcList.size(); i++) {
176: Source source = (Source) srcList.elementAt(i);
177: compileList.addElement(source);
178: }
179: return compileList;
180: }
181:
182: return compileList;
183: }
184:
185: /** Return the files that were actually compiled
186: */
187: public Vector getCompiledFiles() {
188: return compileList;
189: }
190:
191: /** Compile the source files. The compiler adapter can override either this method
192: * ( if it can compile multiple files at once ) or compileSingleFile().
193: * Note that the list includes _all_ sources, findCompileList() can be used to
194: * avoid compiling files that are up-to-date.
195: */
196: public void compile(Vector sourceFiles) throws BuildException {
197: compileList = findCompileList(sourceFiles);
198:
199: log("Compiling " + compileList.size() + " out of "
200: + sourceFiles.size());
201: Enumeration en = compileList.elements();
202: while (en.hasMoreElements()) {
203: Source source = (Source) en.nextElement();
204: compileSingleFile(source);
205: }
206: }
207:
208: /** Compile single file
209: */
210: public void compileSingleFile(Source sourceObj)
211: throws BuildException {
212: }
213:
214: protected void displayError(int result, String source,
215: Commandline cmd) throws BuildException {
216: if (result == 0) {
217: String err = errorstream.toString();
218: if (err == null)
219: return;
220: if (err.indexOf("warning") <= 0)
221: return;
222: log("Warnings: ");
223: log(err);
224: return;
225: }
226:
227: log("Compile failed " + result + " " + source);
228: log("Command:" + cmd.toString());
229: log("Output:");
230: if (outputstream != null)
231: log(outputstream.toString());
232: log("StdErr:");
233: if (errorstream != null)
234: log(errorstream.toString());
235:
236: throw new BuildException("Compile failed " + source);
237: }
238:
239: protected void addIncludes(Commandline cmd) {
240: String[] includeList = (includes == null) ? new String[] {}
241: : includes.getIncludePatterns(project);
242: for (int i = 0; i < includeList.length; i++) {
243: cmd.createArgument().setValue("-I" + includeList[i]);
244: }
245: }
246:
247: /** Common cc parameters
248: */
249: protected void addExtraFlags(Commandline cmd) {
250: String extra_cflags = project
251: .getProperty("build.native.extra_cflags");
252: String localCflags = cflags;
253: if (localCflags == null) {
254: localCflags = extra_cflags;
255: } else {
256: if (extra_cflags != null) {
257: localCflags += " " + extra_cflags;
258: }
259: }
260: if (localCflags != null)
261: cmd.createArgument().setLine(localCflags);
262: }
263:
264: protected void addDefines(Commandline cmd) {
265: // Define by default the OS ( as known to java )
266: String os = System.getProperty("java.os");
267:
268: if (defines.size() > 0) {
269: Enumeration defs = defines.elements();
270: while (defs.hasMoreElements()) {
271: Def d = (Def) defs.nextElement();
272: String name = d.getName();
273: String val = d.getValue();
274: if (name == null)
275: continue;
276: String arg = "-D" + name;
277: if (val != null)
278: arg += "=" + val;
279: cmd.createArgument().setValue(arg);
280: }
281: }
282: }
283:
284: protected void addDebug(Commandline cmd) {
285: }
286:
287: protected void addOptimize(Commandline cmd) {
288: }
289:
290: protected void addProfile(Commandline cmd) {
291: }
292: }
|