mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-10-30 18:53:45 +01:00 
			
		
		
		
	git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			405 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			405 lines
		
	
	
		
			14 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.File;
 | |
| import java.io.FileWriter;
 | |
| import java.io.IOException;
 | |
| import java.util.Enumeration;
 | |
| import java.util.Vector;
 | |
| 
 | |
| import net.sf.antcontrib.cpptasks.CCTask;
 | |
| import net.sf.antcontrib.cpptasks.CUtil;
 | |
| import net.sf.antcontrib.cpptasks.LinkerDef;
 | |
| import net.sf.antcontrib.cpptasks.ProcessorDef;
 | |
| import net.sf.antcontrib.cpptasks.ProcessorParam;
 | |
| import net.sf.antcontrib.cpptasks.types.CommandLineArgument;
 | |
| import net.sf.antcontrib.cpptasks.types.LibrarySet;
 | |
| import net.sf.antcontrib.cpptasks.TargetDef;
 | |
| 
 | |
| import org.apache.tools.ant.BuildException;
 | |
| import org.apache.tools.ant.types.Environment;
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * An abstract Linker implementation that performs the link via an external
 | |
|  * command.
 | |
|  *
 | |
|  * @author Adam Murdoch
 | |
|  */
 | |
| public abstract class CommandLineLinker extends AbstractLinker
 | |
| {
 | |
|     private String command;
 | |
|     private Environment env = null;
 | |
|     private String identifier;
 | |
|     private String identifierArg;
 | |
|     private boolean isLibtool;
 | |
|     private String[] librarySets;
 | |
|     private CommandLineLinker libtoolLinker;
 | |
|     private boolean newEnvironment = false;
 | |
|     private String outputSuffix;
 | |
| 
 | |
| 
 | |
|     /** Creates a comand line linker invocation */
 | |
|     public CommandLineLinker(String command,
 | |
|         String identifierArg,
 | |
|         String[] extensions,
 | |
|         String[] ignoredExtensions, String outputSuffix,
 | |
|         boolean isLibtool, CommandLineLinker libtoolLinker)
 | |
|     {
 | |
|         super(extensions, ignoredExtensions);
 | |
|         this.command = command;
 | |
|         this.identifierArg = identifierArg;
 | |
|         this.outputSuffix = outputSuffix;
 | |
|         this.isLibtool = isLibtool;
 | |
|         this.libtoolLinker = libtoolLinker;
 | |
|     }
 | |
|     protected abstract void addBase(long base, Vector args);
 | |
| 
 | |
|     protected abstract void addFixed(Boolean fixed, Vector args);
 | |
| 
 | |
|     abstract protected void addImpliedArgs(boolean debug,
 | |
|       LinkType linkType, Vector args, Boolean defaultflag);
 | |
|     protected abstract void addIncremental(boolean incremental, Vector args);
 | |
| 
 | |
|       //
 | |
|       //  Windows processors handle these through file list
 | |
|       //
 | |
|     protected String[] addLibrarySets(CCTask task, LibrarySet[] libsets, Vector preargs,
 | |
|         Vector midargs, Vector endargs) {
 | |
|         return null;
 | |
|     }
 | |
|     protected abstract void addMap(boolean map, Vector args);
 | |
|     protected abstract void addStack(int stack, Vector args);
 | |
|     protected abstract void addEntry(String entry, Vector args);
 | |
|     
 | |
|     protected LinkerConfiguration createConfiguration(
 | |
|       CCTask task,
 | |
|       LinkType linkType,
 | |
|       ProcessorDef[] baseDefs, LinkerDef specificDef, TargetDef targetPlatform) {
 | |
| 
 | |
|       Vector preargs = new Vector();
 | |
|       Vector midargs = new Vector();
 | |
|       Vector endargs = new Vector();
 | |
|       Vector[] args = new Vector[] { preargs, midargs, endargs };
 | |
| 
 | |
|       LinkerDef[] defaultProviders = new LinkerDef[baseDefs.length+1];
 | |
|       defaultProviders[0] = specificDef;
 | |
|       for(int i = 0; i < baseDefs.length; i++) {
 | |
|         defaultProviders[i+1] = (LinkerDef) baseDefs[i];
 | |
|       }
 | |
|       //
 | |
|       //   add command line arguments inherited from <cc> element
 | |
|       //     any "extends" and finally the specific CompilerDef
 | |
|       CommandLineArgument[] commandArgs;
 | |
|       for(int i = defaultProviders.length-1; i >= 0; i--) {
 | |
|         commandArgs = defaultProviders[i].getActiveProcessorArgs();
 | |
|         for(int j = 0; j < commandArgs.length; j++) {
 | |
|           args[commandArgs[j].getLocation()].
 | |
|                 addElement(commandArgs[j].getValue());
 | |
|         }
 | |
|       }
 | |
| 
 | |
|         Vector params = new Vector();
 | |
|         //
 | |
|         //   add command line arguments inherited from <cc> element
 | |
|         //     any "extends" and finally the specific CompilerDef
 | |
|         ProcessorParam[] paramArray;
 | |
|         for (int i = defaultProviders.length - 1; i >= 0; i--) {
 | |
|             paramArray = defaultProviders[i].getActiveProcessorParams();
 | |
|             for (int j = 0; j < paramArray.length; j++) {
 | |
|                 params.add(paramArray[j]);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         paramArray = (ProcessorParam[])(params.toArray(new ProcessorParam[params.size()]));
 | |
| 
 | |
|         boolean debug = specificDef.getDebug(baseDefs,0);
 | |
| 
 | |
|       
 | |
|       String startupObject = getStartupObject(linkType);
 | |
|       Boolean defaultflag = specificDef.getDefaultflag(defaultProviders, 1);
 | |
|       addImpliedArgs(debug, linkType, preargs, defaultflag);
 | |
|       addIncremental(specificDef.getIncremental(defaultProviders,1), preargs);
 | |
|       addFixed(specificDef.getFixed(defaultProviders,1), preargs);
 | |
|       addMap(specificDef.getMap(defaultProviders,1), preargs);
 | |
|       addBase(specificDef.getBase(defaultProviders,1), preargs);
 | |
|       addStack(specificDef.getStack(defaultProviders,1), preargs);
 | |
|       addEntry(specificDef.getEntry(defaultProviders, 1), preargs);
 | |
| 
 | |
|       String[] libnames = null;
 | |
|       LibrarySet[] libsets = specificDef.getActiveLibrarySets(defaultProviders,1);
 | |
|       if (libsets.length > 0) {
 | |
|         libnames = addLibrarySets(task, libsets, preargs, midargs, endargs);
 | |
|       }
 | |
| 
 | |
|       StringBuffer buf = new StringBuffer(getIdentifier());
 | |
|       for (int i = 0; i < 3; i++) {
 | |
|         Enumeration argenum = args[i].elements();
 | |
|         while (argenum.hasMoreElements()) {
 | |
|            buf.append(' ');
 | |
|            buf.append(argenum.nextElement().toString());
 | |
|         }
 | |
|       }
 | |
|       String configId = buf.toString();
 | |
| 
 | |
|       String[][] options = new String[][] {
 | |
|         new String[args[0].size() + args[1].size()],
 | |
|         new String[args[2].size()] };
 | |
|       args[0].copyInto(options[0]);
 | |
|       int offset = args[0].size();
 | |
|       for (int i = 0; i < args[1].size(); i++) {
 | |
|         options[0][i+offset] = (String) args[1].elementAt(i);
 | |
|       }
 | |
|       args[2].copyInto(options[1]);
 | |
| 
 | |
| 
 | |
|       boolean rebuild = specificDef.getRebuild(baseDefs,0);
 | |
|       boolean map = specificDef.getMap(defaultProviders,1);
 | |
| 
 | |
|       //task.log("libnames:"+libnames.length, Project.MSG_VERBOSE);
 | |
|       return new CommandLineLinkerConfiguration(this,configId,options,
 | |
|               paramArray,
 | |
|               rebuild,map,libnames, startupObject);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Allows drived linker to decorate linker option.
 | |
|      * Override by GccLinker to prepend a "-Wl," to
 | |
|      * pass option to through gcc to linker.
 | |
|      *
 | |
|      * @param buf buffer that may be used and abused in the decoration process,
 | |
|      * must not be null.
 | |
|      * @param arg linker argument
 | |
|      */
 | |
|     protected String decorateLinkerOption(StringBuffer buf, String arg) {
 | |
|       return arg;
 | |
|     }
 | |
| 
 | |
|     protected final String getCommand() {
 | |
|       return command;
 | |
|     }
 | |
|     protected abstract String getCommandFileSwitch(String commandFile);
 | |
| 
 | |
| 
 | |
|      public String getIdentifier() {
 | |
|       if(identifier == null) {
 | |
|         if (identifierArg == null) {
 | |
|           identifier = getIdentifier(new String[] { command }, command);
 | |
|         } else {
 | |
|           identifier = getIdentifier(new String[] { command, identifierArg },
 | |
|             command);
 | |
|         }
 | |
|       }
 | |
|       return identifier;
 | |
|     }
 | |
|     public final CommandLineLinker getLibtoolLinker() {
 | |
|       if (libtoolLinker != null) {
 | |
|         return libtoolLinker;
 | |
|       }
 | |
|       return this;
 | |
|     }
 | |
|     protected abstract int getMaximumCommandLength();
 | |
| 
 | |
|     public String getOutputFileName(String baseName) {
 | |
|         return baseName + outputSuffix;
 | |
|     }
 | |
| 
 | |
|     protected String[] getOutputFileSwitch(CCTask task, String outputFile) {
 | |
|         return getOutputFileSwitch(outputFile);
 | |
|     }
 | |
|     protected abstract String[] getOutputFileSwitch(String outputFile);
 | |
|     protected String getStartupObject(LinkType linkType) {
 | |
|       return null;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Performs a link using a command line linker
 | |
|      *
 | |
|      */
 | |
|     public void link(CCTask task,
 | |
|                      File outputFile,
 | |
|                      String[] sourceFiles,
 | |
|                      CommandLineLinkerConfiguration config)
 | |
|                      throws BuildException
 | |
|     {
 | |
|         File parentDir = new File(outputFile.getParent());
 | |
|         String parentPath;
 | |
|         try {
 | |
|           parentPath = parentDir.getCanonicalPath();
 | |
|         } catch(IOException ex) {
 | |
|           parentPath = parentDir.getAbsolutePath();
 | |
|         }
 | |
|         String[] execArgs = prepareArguments(task, parentPath,outputFile.getName(),
 | |
|             sourceFiles, config);
 | |
|         int commandLength = 0;
 | |
|         for(int i = 0; i < execArgs.length; i++) {
 | |
|           commandLength += execArgs[i].length() + 1;
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         //   if command length exceeds maximum
 | |
|         //       (1024 for Windows) then create a temporary
 | |
|         //       file containing everything but the command name
 | |
|         if(commandLength >= this.getMaximumCommandLength()) {
 | |
|           try {
 | |
|             execArgs = prepareResponseFile(outputFile,execArgs);
 | |
|           }
 | |
|           catch(IOException ex) {
 | |
|             throw new BuildException(ex);
 | |
|           }
 | |
|         }
 | |
|         
 | |
|         int retval = runCommand(task,parentDir,execArgs);        
 | |
|         //
 | |
|         //   if the process returned a failure code then
 | |
|         //       throw an BuildException
 | |
|         //
 | |
|         if(retval != 0) {
 | |
|           //
 | |
|           //   construct the exception
 | |
|           //
 | |
|           throw new BuildException(this.getCommand() + " failed with return code " + retval, task.getLocation());
 | |
|         }
 | |
|         
 | |
|     }
 | |
| 
 | |
| 
 | |
|     /**
 | |
|      * Prepares argument list for exec command.  Will return null
 | |
|      * if command line would exceed allowable command line buffer.
 | |
|      *
 | |
|      * @param outputFile linker output file
 | |
|      * @param sourceFiles linker input files (.obj, .o, .res)
 | |
|      * @param args linker arguments
 | |
|      * @return arguments for runTask
 | |
|      */
 | |
|     protected String[] prepareArguments(
 | |
|         CCTask task,
 | |
|         String outputDir,
 | |
|         String outputFile,
 | |
|         String[] sourceFiles,
 | |
|         CommandLineLinkerConfiguration config) {
 | |
|                         
 | |
|         String[] preargs = config.getPreArguments();
 | |
|         String[] endargs = config.getEndArguments();
 | |
|         String outputSwitch[] =  getOutputFileSwitch(task, outputFile);
 | |
|         int allArgsCount = preargs.length + 1 + outputSwitch.length +
 | |
|                 sourceFiles.length + endargs.length;
 | |
|         if (isLibtool) {
 | |
|           allArgsCount++;
 | |
|         }
 | |
|         String[] allArgs = new String[allArgsCount];
 | |
|         int index = 0;
 | |
|         if (isLibtool) {
 | |
|           allArgs[index++] = "libtool";
 | |
|         }
 | |
|         allArgs[index++] = this.getCommand();
 | |
|         StringBuffer buf = new StringBuffer();
 | |
|         for (int i = 0; i < preargs.length; i++) {
 | |
|           allArgs[index++] = decorateLinkerOption(buf, preargs[i]);
 | |
|         }
 | |
|         for (int i = 0; i < outputSwitch.length; i++) {
 | |
|           allArgs[index++] = outputSwitch[i];
 | |
|         }
 | |
|         for (int i = 0; i < sourceFiles.length; i++) {
 | |
|           allArgs[index++] = prepareFilename(buf,outputDir,sourceFiles[i]);
 | |
|         }
 | |
|         for (int i = 0; i < endargs.length; i++) {
 | |
|           allArgs[index++] = decorateLinkerOption(buf, endargs[i]);
 | |
|         }
 | |
|         return allArgs;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Processes filename into argument form
 | |
|      *
 | |
|      */
 | |
|     protected String prepareFilename(StringBuffer buf,
 | |
|       String outputDir, String sourceFile) {
 | |
|       String relativePath = CUtil.getRelativePath(outputDir,
 | |
|         new File(sourceFile));
 | |
|       return quoteFilename(buf,relativePath);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Prepares argument list to execute the linker using a
 | |
|      * response file.
 | |
|      *
 | |
|      * @param outputFile linker output file
 | |
|      * @param args output of prepareArguments
 | |
|      * @return arguments for runTask
 | |
|      */
 | |
|     protected String[] prepareResponseFile(File outputFile,String[] args) throws IOException
 | |
|     {
 | |
|         String baseName = outputFile.getName();
 | |
|         File commandFile = new File(outputFile.getParent(),baseName + ".rsp");
 | |
|         FileWriter writer = new FileWriter(commandFile);
 | |
|         int execArgCount = 1;
 | |
|         if (isLibtool) {
 | |
|           execArgCount++;
 | |
|         }
 | |
|         String[] execArgs = new String[execArgCount+1];
 | |
|         for (int i = 0; i < execArgCount; i++) {
 | |
|           execArgs[i] = args[i];
 | |
|         }
 | |
|         execArgs[execArgCount] = getCommandFileSwitch(commandFile.toString());
 | |
|         for(int i = execArgCount; i < args.length; i++) {
 | |
|         	//
 | |
|         	//   if embedded space and not quoted then
 | |
|         	//       quote argument
 | |
|           if (args[i].indexOf(" ") >= 0 && args[i].charAt(0) != '\"') {
 | |
|           	writer.write('\"');
 | |
|           	writer.write(args[i]);
 | |
|           	writer.write("\"\n");
 | |
|           } else {
 | |
|           	writer.write(args[i]);
 | |
|             writer.write('\n');
 | |
|           }
 | |
|         }
 | |
|         writer.close();
 | |
|         return execArgs;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     protected String quoteFilename(StringBuffer buf,String filename) {
 | |
|       if(filename.indexOf(' ') >= 0) {
 | |
|         buf.setLength(0);
 | |
|         buf.append('\"');
 | |
|         buf.append(filename);
 | |
|         buf.append('\"');
 | |
|         return buf.toString();
 | |
|       }
 | |
|       return filename;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * This method is exposed so test classes can overload
 | |
|      * and test the arguments without actually spawning the
 | |
|      * compiler
 | |
|      */
 | |
|     protected int runCommand(CCTask task, File workingDir,String[] cmdline)
 | |
|       throws BuildException {
 | |
|       return CUtil.runCommand(task,workingDir,cmdline, newEnvironment, env);
 | |
|     }
 | |
| 
 | |
|     protected final void setCommand(String command) {
 | |
|         this.command = command;
 | |
|     }
 | |
| 
 | |
| }
 |