mirror of https://github.com/acidanthera/audk.git
206 lines
8.3 KiB
Java
206 lines
8.3 KiB
Java
/*
|
|
*
|
|
* Copyright 2002-2004 The Ant-Contrib project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
package net.sf.antcontrib.cpptasks.compiler;
|
|
import java.io.BufferedReader;
|
|
import java.io.File;
|
|
import java.io.FileReader;
|
|
import java.io.IOException;
|
|
import java.io.Reader;
|
|
import java.util.Vector;
|
|
import net.sf.antcontrib.cpptasks.CCTask;
|
|
import net.sf.antcontrib.cpptasks.CUtil;
|
|
import net.sf.antcontrib.cpptasks.CompilerDef;
|
|
import net.sf.antcontrib.cpptasks.DependencyInfo;
|
|
import net.sf.antcontrib.cpptasks.ProcessorDef;
|
|
import net.sf.antcontrib.cpptasks.parser.Parser;
|
|
import net.sf.antcontrib.cpptasks.TargetDef;
|
|
|
|
/**
|
|
* An abstract compiler implementation.
|
|
*
|
|
* @author Adam Murdoch
|
|
* @author Curt Arnold
|
|
*/
|
|
public abstract class AbstractCompiler extends AbstractProcessor
|
|
implements
|
|
Compiler {
|
|
private static final String[] emptyIncludeArray = new String[0];
|
|
private String outputSuffix;
|
|
protected AbstractCompiler(String[] sourceExtensions,
|
|
String[] headerExtensions, String outputSuffix) {
|
|
super(sourceExtensions, headerExtensions);
|
|
this.outputSuffix = outputSuffix;
|
|
}
|
|
/**
|
|
* Checks file name to see if parse should be attempted
|
|
*
|
|
* Default implementation returns false for files with extensions '.dll',
|
|
* 'tlb', '.res'
|
|
*
|
|
*/
|
|
protected boolean canParse(File sourceFile) {
|
|
String sourceName = sourceFile.toString();
|
|
int lastPeriod = sourceName.lastIndexOf('.');
|
|
if (lastPeriod >= 0 && lastPeriod == sourceName.length() - 4) {
|
|
String ext = sourceName.substring(lastPeriod).toUpperCase();
|
|
if (ext.equals(".DLL") || ext.equals(".TLB") || ext.equals(".RES")) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
abstract protected CompilerConfiguration createConfiguration(CCTask task,
|
|
LinkType linkType, ProcessorDef[] baseConfigs,
|
|
CompilerDef specificConfig, TargetDef targetPlatform);
|
|
public ProcessorConfiguration createConfiguration(CCTask task,
|
|
LinkType linkType, ProcessorDef[] baseConfigs,
|
|
ProcessorDef specificConfig, TargetDef targetPlatform) {
|
|
if (specificConfig == null) {
|
|
throw new NullPointerException("specificConfig");
|
|
}
|
|
return createConfiguration(task, linkType, baseConfigs,
|
|
(CompilerDef) specificConfig, targetPlatform);
|
|
}
|
|
abstract protected Parser createParser(File sourceFile);
|
|
protected String getBaseOutputName(String inputFile) {
|
|
int lastSlash = inputFile.lastIndexOf('/');
|
|
int lastReverse = inputFile.lastIndexOf('\\');
|
|
int lastSep = inputFile.lastIndexOf(File.separatorChar);
|
|
if (lastReverse > lastSlash) {
|
|
lastSlash = lastReverse;
|
|
}
|
|
if (lastSep > lastSlash) {
|
|
lastSlash = lastSep;
|
|
}
|
|
int lastPeriod = inputFile.lastIndexOf('.');
|
|
if (lastPeriod < 0) {
|
|
lastPeriod = inputFile.length();
|
|
}
|
|
return inputFile.substring(lastSlash + 1, lastPeriod);
|
|
}
|
|
public String getOutputFileName(String inputFile) {
|
|
//
|
|
// if a recognized input file
|
|
//
|
|
if (bid(inputFile) > 1) {
|
|
String baseName = getBaseOutputName(inputFile);
|
|
return baseName + outputSuffix;
|
|
}
|
|
return null;
|
|
}
|
|
/**
|
|
* Returns dependency info for the specified source file
|
|
*
|
|
* @param task
|
|
* task for any diagnostic output
|
|
* @param source
|
|
* file to be parsed
|
|
* @param includePath
|
|
* include path to be used to resolve included files
|
|
*
|
|
* @param sysIncludePath
|
|
* sysinclude path from build file, files resolved using
|
|
* sysInclude path will not participate in dependency analysis
|
|
*
|
|
* @param envIncludePath
|
|
* include path from environment variable, files resolved with
|
|
* envIncludePath will not participate in dependency analysis
|
|
*
|
|
* @param baseDir
|
|
* used to produce relative paths in DependencyInfo
|
|
* @param includePathIdentifier
|
|
* used to distinguish DependencyInfo's from different include
|
|
* path settings
|
|
*
|
|
* @author Curt Arnold
|
|
*/
|
|
public final DependencyInfo parseIncludes(CCTask task, File source,
|
|
File[] includePath, File[] sysIncludePath, File[] envIncludePath,
|
|
File baseDir, String includePathIdentifier) {
|
|
//
|
|
// if any of the include files can not be identified
|
|
// change the sourceLastModified to Long.MAX_VALUE to
|
|
// force recompilation of anything that depends on it
|
|
long sourceLastModified = source.lastModified();
|
|
File[] sourcePath = new File[1];
|
|
sourcePath[0] = new File(source.getParent());
|
|
Vector onIncludePath = new Vector();
|
|
Vector onSysIncludePath = new Vector();
|
|
String baseDirPath;
|
|
try {
|
|
baseDirPath = baseDir.getCanonicalPath();
|
|
} catch (IOException ex) {
|
|
baseDirPath = baseDir.toString();
|
|
}
|
|
String relativeSource = CUtil.getRelativePath(baseDirPath, source);
|
|
String[] includes = emptyIncludeArray;
|
|
if (canParse(source)) {
|
|
Parser parser = createParser(source);
|
|
try {
|
|
Reader reader = new BufferedReader(new FileReader(source));
|
|
parser.parse(reader);
|
|
includes = parser.getIncludes();
|
|
} catch (IOException ex) {
|
|
task.log("Error parsing " + source.toString() + ":"
|
|
+ ex.toString());
|
|
includes = new String[0];
|
|
}
|
|
}
|
|
for (int i = 0; i < includes.length; i++) {
|
|
String includeName = includes[i];
|
|
if (!resolveInclude(includeName, sourcePath, onIncludePath)) {
|
|
if (!resolveInclude(includeName, includePath, onIncludePath)) {
|
|
if (!resolveInclude(includeName, sysIncludePath,
|
|
onSysIncludePath)) {
|
|
if (!resolveInclude(includeName, envIncludePath,
|
|
onSysIncludePath)) {
|
|
//
|
|
// this should be enough to require us to reparse
|
|
// the file with the missing include for dependency
|
|
// information without forcing a rebuild
|
|
sourceLastModified++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (int i = 0; i < onIncludePath.size(); i++) {
|
|
String relativeInclude = CUtil.getRelativePath(baseDirPath,
|
|
(File) onIncludePath.elementAt(i));
|
|
onIncludePath.setElementAt(relativeInclude, i);
|
|
}
|
|
for (int i = 0; i < onSysIncludePath.size(); i++) {
|
|
String relativeInclude = CUtil.getRelativePath(baseDirPath,
|
|
(File) onSysIncludePath.elementAt(i));
|
|
onSysIncludePath.setElementAt(relativeInclude, i);
|
|
}
|
|
return new DependencyInfo(includePathIdentifier, relativeSource,
|
|
sourceLastModified, onIncludePath, onSysIncludePath);
|
|
}
|
|
protected boolean resolveInclude(String includeName, File[] includePath,
|
|
Vector onThisPath) {
|
|
for (int i = 0; i < includePath.length; i++) {
|
|
File includeFile = new File(includePath[i], includeName);
|
|
if (includeFile.exists()) {
|
|
onThisPath.addElement(includeFile);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|