1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  package com.github.maven_nar.cpptasks.compiler;
21  
22  import java.io.BufferedReader;
23  import java.io.File;
24  import java.io.FileReader;
25  import java.io.IOException;
26  import java.io.Reader;
27  import java.util.Vector;
28  
29  import org.apache.commons.io.FilenameUtils;
30  
31  import com.github.maven_nar.cpptasks.CCTask;
32  import com.github.maven_nar.cpptasks.CUtil;
33  import com.github.maven_nar.cpptasks.CompilerDef;
34  import com.github.maven_nar.cpptasks.DependencyInfo;
35  import com.github.maven_nar.cpptasks.ProcessorDef;
36  import com.github.maven_nar.cpptasks.TargetDef;
37  import com.github.maven_nar.cpptasks.VersionInfo;
38  import com.github.maven_nar.cpptasks.parser.Parser;
39  
40  
41  
42  
43  
44  
45  
46  public abstract class AbstractCompiler extends AbstractProcessor implements Compiler {
47    private static final String[] emptyIncludeArray = new String[0];
48    private final String outputSuffix;
49    protected File workDir;
50    protected File objDir;
51  
52    protected AbstractCompiler(final String[] sourceExtensions, final String[] headerExtensions, final String outputSuffix) {
53      super(sourceExtensions, headerExtensions);
54      this.outputSuffix = outputSuffix;
55    }
56  
57    
58  
59  
60  
61  
62  
63  
64    protected boolean canParse(final File sourceFile) {
65      final String sourceName = sourceFile.toString();
66      final int lastPeriod = sourceName.lastIndexOf('.');
67      if (lastPeriod >= 0 && lastPeriod == sourceName.length() - 4) {
68        final String ext = sourceName.substring(lastPeriod).toUpperCase();
69        if (ext.equals(".DLL") || ext.equals(".TLB") || ext.equals(".RES")) {
70          return false;
71        }
72      }
73      return true;
74    }
75  
76    abstract protected CompilerConfiguration createConfiguration(CCTask task, LinkType linkType,
77        ProcessorDef[] baseConfigs, CompilerDef specificConfig, TargetDef targetPlatform, VersionInfo versionInfo);
78  
79    @Override
80    public ProcessorConfiguration createConfiguration(final CCTask task, final LinkType linkType,
81        final ProcessorDef[] baseConfigs, final ProcessorDef specificConfig, final TargetDef targetPlatform,
82        final VersionInfo versionInfo) {
83      if (specificConfig == null) {
84        throw new NullPointerException("specificConfig");
85      }
86      return createConfiguration(task, linkType, baseConfigs, (CompilerDef) specificConfig, targetPlatform, versionInfo);
87    }
88  
89    abstract protected Parser createParser(File sourceFile);
90    
91    protected String getBaseOutputName(final String inputFile) {
92      return FilenameUtils.getBaseName(inputFile);
93    }
94  
95    @Override
96    public String[] getOutputFileNames(final String inputFile, final VersionInfo versionInfo) {
97      
98      
99      
100     if (bid(inputFile) > 1) {
101       final String baseName = getBaseOutputName(inputFile);
102       return new String[] {
103         baseName + this.outputSuffix
104       };
105     }
106     return new String[0];
107   }
108 
109   
110 
111 
112 
113 
114 
115 
116 
117 
118 
119 
120 
121 
122 
123 
124 
125 
126 
127 
128 
129 
130 
131 
132 
133 
134   public final DependencyInfo parseIncludes(final CCTask task, final File source, final File[] includePath,
135       final File[] sysIncludePath, final File[] envIncludePath, final File baseDir, final String includePathIdentifier) {
136     
137     
138     
139     
140     long sourceLastModified = source.lastModified();
141     final File[] sourcePath = new File[1];
142     sourcePath[0] = new File(source.getParent());
143     final Vector onIncludePath = new Vector();
144     final Vector onSysIncludePath = new Vector();
145     String baseDirPath;
146     try {
147       baseDirPath = baseDir.getCanonicalPath();
148     } catch (final IOException ex) {
149       baseDirPath = baseDir.toString();
150     }
151     final String relativeSource = CUtil.getRelativePath(baseDirPath, source);
152     String[] includes = emptyIncludeArray;
153     if (canParse(source)) {
154       final Parser parser = createParser(source);
155       try {
156         final Reader reader = new BufferedReader(new FileReader(source));
157         parser.parse(reader);
158         includes = parser.getIncludes();
159       } catch (final IOException ex) {
160         task.log("Error parsing " + source.toString() + ":" + ex.toString());
161         includes = new String[0];
162       }
163     }
164     for (final String include : includes) {
165       if (!resolveInclude(include, sourcePath, onIncludePath)) {
166         if (!resolveInclude(include, includePath, onIncludePath)) {
167           if (!resolveInclude(include, sysIncludePath, onSysIncludePath)) {
168             if (!resolveInclude(include, envIncludePath, onSysIncludePath)) {
169               
170               
171               
172               
173               sourceLastModified += 2 * CUtil.FILETIME_EPSILON;
174             }
175           }
176         }
177       }
178     }
179     for (int i = 0; i < onIncludePath.size(); i++) {
180       final String relativeInclude = CUtil.getRelativePath(baseDirPath, (File) onIncludePath.elementAt(i));
181       onIncludePath.setElementAt(relativeInclude, i);
182     }
183     for (int i = 0; i < onSysIncludePath.size(); i++) {
184       final String relativeInclude = CUtil.getRelativePath(baseDirPath, (File) onSysIncludePath.elementAt(i));
185       onSysIncludePath.setElementAt(relativeInclude, i);
186     }
187     return new DependencyInfo(includePathIdentifier, relativeSource, sourceLastModified, onIncludePath,
188         onSysIncludePath);
189   }
190 
191   protected boolean resolveInclude(final String includeName, final File[] includePath, final Vector onThisPath) {
192     for (final File element : includePath) {
193       final File includeFile = new File(element, includeName);
194       if (includeFile.exists()) {
195         onThisPath.addElement(includeFile);
196         return true;
197       }
198     }
199     return false;
200   }
201 
202   public final String getOutputSuffix() {
203     return this.outputSuffix;
204   }
205 
206   public void setWorkDir(final File workDir) {
207     this.workDir = workDir;
208   }
209 
210   public void setObjDir(final File objDir) {
211     this.objDir = objDir;
212   }
213 }